robertkosten / providence
A dev-dependency, installing some git commit hooks to ensure code style, etc.
Requires
Requires (Dev)
- zandev/shunit2: 2.1.6
README
providence
A dev-dependency, installing some git commit hooks to ensure code style, etc. Add to your composer.json as require-dev.
It is safe use dev-master
, as this project follows git-flow
and only the latest tagged releases are ever merged into master.
"require-dev" : {
"robertkosten/providence" : "dev-master"
}
Then put the install command (With the optional project type) into your scripts (of course you can also do the installation manually, but you lose the advantage of having them installed automatically for every contributor):
"scripts" : {
"post-install-cmd" : [
"vendor/bin/providence install php-library"
],
"post-update-cmd" : [
"vendor/bin/providence install php-library"
]
}
If you specify a project type the installer will ensure that a .providence file is placed in your project root referencing the type. This file will eventually contain all providence configuration options that you want to enforce on your project.
To uninstall the hooks again, simply use ./vendor/bin/providence uninstall
.
Configuration (.providence & git-config)
Providence provides many configuration options that can be set in three ways. At the lowest precendence are those
provided by the project-type or default
. These can be overridden on a project level by placing a .providence file in
the projects root. Both files follow the same syntax, so have a peek at vendor/robertkosten/providence/defaults
when
in doubt. The general idea is simple though:
# Comments and blank lines work as expected
pre-commit.php.blacklist.list exit|die
On the very top of the precendence chain lie git-config entries, which follow the exact same naming scheme, though
prefixed with providence.
:
# Setting an option
git config providence.commit-msg.enabled 0
# Removing an option
git config --unset providence.commit-msg.enabled
Setup
The setup.
set of options are for general settings, like defining the defaults setup.default
or enabling a more
verbose mode setup.verbose
.
Filesets
Also part of setup are the filesets. If you know ant or phing you are likely familiar with the concept. A fileset
defines a group of globbing expressions used to identify files which can then be referred to by a single name.
For example setup.fileset.php \*.php|\*.php5
(*
needs to be escaped) creates a fileset named php
which will
contain all files ending in either .php
or .php5
, so any checks specificaly for php files (like php-lint
) can use
it to only apply to them (It wouldn't make much sense to run that check against you README.md, would it?).
Providence has one built-in fileset, originally only populated for the commit-msg
hook, called xt-auto
(for "Extra"
and "Automatically filled"), which will then contain exactly one file, the one containing the commit message (And now
you know how git manages to let you use your favorite editor to type it in the first place). For the pre-commit
hook
it contains a reference to /dev/null, so it can be used to trigger modules designed to run on the entire repository,
like flow-protect-master
.
There is also a group of filesets called xt-mime-*
which are configured similarly to normal filesets, but contain
globbing expressions for the MIME-type (as reported by file -b --mime-type
). For example xt-mime-text
is configured
to match all text/*
files (in php-library
).
Ignores
Extremely similar to filesets, ignores specify globbing patterns that are never to be checked by any hook or module. The
most obvious example is the .providence file, which can easily, for example when specifying blacklists, contain
precisely the data forbidden in other files. As such it is added to a default providence
ignore list. If you examine
the .providence of providence itself you will find two others, with similar rationale, one excluding the entire defaults
directory and the other all files under test/files that contain -error.
, as these, naturally, are not valid for some
module.
Treat ignores similarly to .gitignore: Use them sparingly and try to be as precise in matching your intended set as possible to avoid unpleasant surprises.
Hooks and Modules
All things start with enabled
, the top level option to enable any kind of processing on providences part. You will
find that in all defaults (barring none
, of course) and it is intended as a quick way to disable all hooks when needed
without fiddling with which hook, fileset and module are causing trouble.
Most things are assigned to a hook (the list of currently supported hooks can be gleaned from
./vendor/bin/providence list
), which is simply the name of a git hook (I intend to support
git flow hooks as soon as possible) like commit-msg
. Every hook can be
en-/disabled individually, and like all enabled
options it defaults to off, so you're again likely to see a few
HOOK.enabled
entries in the defaults.
After the hook come the filesets, which, you've guessed it, can be en-/disabled for the hook: HOOK.FILESET.enabled
.
The finally the modules HOOK.FILESET.MODULE.enabled
, which may have further options besides enabled
, the debug
module for example, also supports a "quiet mode", enabled via HOOK.FILESET.debug.quiet
. These options, or parameters,
can either be optional and use a default value then, or required (Running blacklist with an empty list makes no sense,
after all). See ./vendor/bin/providence list -v
to learn about all the parameters and default values.
Example
A quick example may help:
setup.fileset.gitignore .gitignore
setup.fileset.php \*.php|\*.php5
enabled 1
commit-msg.enabled 1
commit-msg.xt-auto.enabled 1
commit-msg.xt-auto.format-github.enabled 1
pre-commit.enabled 1
pre-commit.gitignore.enabled 1
pre-commit.gitignore.blacklist.enabled 1
pre-commit.gitignore.blacklist.list .directory|.DS_Store|composer.phar|.buildpath|.project|.settings|.idea
pre-commit.gitignore.whitelist.enabled 1
pre-commit.gitignore.whitelist.list vendor
pre-commit.php.enabled 1
pre-commit.php.php-lint.enabled 1
pre-commit.php.blacklist.enabled 1
pre-commit.php.blacklist.list print_r|var_dump|debug_print_backtrace|eval|md5|sha1|ini_set|exit|die|ereg_|__DIR__|__FILE__|sleep|global|include|?>
This is straight from the php-library
default set, which demonstrates all our features nicely. First two filesets are
defined, gitignore
(matching only the .gitignore file) and php
(matching files ending in .php
or .php5
). Then
the global enable
to switch providence on.
Next come the configuration for out two hooks, commit-msg
and pre-commit
. Both are enabled
as a first step.
commit-msg
then uses the built-in xt-auto
fileset, while pre-commit
wants to use both of our defined filesets for
different modules. Each fileset needs to be enabled
again (Fine-grained control can be annoying). Most modules used
are not very interesting in this case, commit-msg
just wants to check the xt-auto
files to conform to the github
format. And pre-commit
wants to lint and blacklist php
files and has both a black- and a whitelist for the
gitignore
. Let's pick the latter as an example: It is enabled
, of course, and has a parameter called list
, which
is configured to contain a single item vendor
. Simply speaking this ensures that your .gitignore file can only be
committed when it contains the string vendor
.
./vendor/bin/providence
This script offers small helper commands in addition to the vast array of configuration options.
on/off
Shortcut to save providence.enabled 1
(or 0
) in your local git-config.
list
This command lists all available configuration options supported by providence, with additional information available
via the -v
switch.
generate
If you're ever worried that I might change the defaults for your project-type, this command offers to bake your current configuration (defaults, .providence and git-config) into one static .providence file (or optionally any other filename). You really shouldn't though, the defaults are getting better all the time ;-)
clean
Have added half a dozen git-config options and don't want to figure out how to simply unset them all again? With clean
all options prefixed with providence.
are automatically removed from your local config.
readme (& license)
Want a quick peek at the documentation (or the MIT license), these commands will quickly open them in less
, so you do
not have to remember to type less vendor/robertkosten/providence/README.md
yourself.
install / uninstall
Providence works via git-hooks and they need to be placed in .git/hooks
. To put the in place (or remove them again)
these commands are available. Both will not touch any actual files already there (But will complain about any
conflicts), though any hooks present as symbolic links will be replaced with the ones for providence.
The install script optionally takes the name of a project-type as argument (As seen in the example composer.json scripts
section) and, if given one, will ensure that a .providence file is present in your project root and that it contains the
correct setup.default PROJECT-TYPE
line (So if you're switching to a static .providence you should also remove the
project-type from your scripts-section).
debug
Of course a complicated little tool such as providence has a few bugs here and there and if you want a peek under the hood, to see what values are actually set internally, use this command. Its output is also invaluable when sending in bug reports of course.
Project Types / Default configurations
Providence provides different sets of default configurations for different purposes. These are expanded and modified
over time, of course, but you may rely on them sticking to current best-practices as so considered by the
php-fig, composer and Symfony2. I will
err on the side of being a little too strict, so you have to make a conscious (and documented, in your projects'
.providence) decision to be relaxed about individual choices. Providence itself used to be more lax about requiring
github issue numbers in every commit message before 0.0.4
, for example, but still ignores the
merge markers that are present in defaults/php-library
.
none
The default project type and the one used when generating a static .providence. It does not and will never contain any configuration, with it set you start from a clean slate, providence will not run any actions whatsoever via its hooks.
php-library
The recommended option for small php libraries that do not contain any (X)HTML, CSS, etc., just a few php classes in a composerified project.
shell-project
Tools consoting mostly of shell code, like providence itself. Has very few modules active, mostly to ensure encoding, etc.
Hooks
The hooks used by providence are entirly virtual, just symbolic links with the correct names, so extending the list of
supported hooks is pretty painless, the only difficulty being hooks that require new ways to collect the files to check
(Currently there is xt-auto
for commit-msg
and the currently staged files for everything else), pre-push for example
would not work with the current code.
commit-msg
This hook only makes sense in conjunction with the built-in xt-auto
fileset, which will then include exactly the
temporary file containing the commit message. Currently only the format-*
modules are of any use with it (and vice
versa).
pre-commit
The heavy lifter. It will run all your staged files (so either added via git add
or git commit -a
) through the
configured modules and prevent you from comitting anything bad. Unstaged changes are ignored.
Modules
Modules provide the actual checks themselves, together with listing the parameters, documentation and defaults. Most TODOs for providence are more modules. And they are easy to write and test. Jump in! Pull requests welcome ;-)
Use /vendor/bin/providence list -v
to get the most recent list of parameters and what they mean.
blacklist
Checks the file for forbidden strings, e.g. debugging functions, deprecated functionality, etc. Optionally can work with regular expressions, though only one can be listed then, for syntax reasons.
bom (byte order mark)
Detects unicode files starting with a BOM, optionally can require it instead.
composer-validate
php composer.phar validate
if there is a composer.phar
in the project root, otherwise composer validate
.
debug
A dummy module that can be used to see what files are processed in any given fileset.
encoding
Ensures that the file is in a suitable encoding (as reported by file -b --mime-encoding
). Multiple values can be
configured, which is especially useful for utf-8
which often masks as us-ascii
since it is a strict superset.
flow-protect-master
One of the modules supporting the git flow development model.
It is designed to prevent any accidental commits to the master branch. It recommended to use this with the xt-auto
fileset so it will always be triggered. It will ignore any file input, but is clever enough to scan your git-config for
usage of either the official git flow plugin or the
AVH variant to determine the master branch name.
format-github
Designed to work with the commit-msg
hook and xt-auto
fileset (Though it would work with any other combination as
well, just not very useful) this checks that the file contents (aka the commit message) either begin with a reference to
an issue on github followed by a colon and a space (e.g. "#1890: Adding Lovecraft") or follow the
github pattern for automatically closing the
issue (e.g. "Closes #1937 Lovecraft Removed").
format-rally
Designed to work with the commit-msg
hook and xt-auto
fileset (Though it would work with any other combination as
well, just not very useful) this checks that the file contents (aka the commit message) either begin with a reference to
a Rally story followed by a colon and a space (e.g. "US1890: Adding Lovecraft").
lineendings
Detects dos line endings instead of unix ones, optionally can be set the other way around.
php-cs
The original raison d'être of providence, a module that checks php files against phpcs.
php-lint
php -l
, what more is there to say?
shell-command
Will run any arbitrary shell command, used as the basis of many other modules (e.g. php-lint, composer-validate).
tabs
Detects tab characters at the beginning of lines, optionally can require them.
whitelist
The opposite of blacklist
, this one requires a set of strings, e.g. excluding vendor
in .gitignore, etc.
Optionally can work with regular expressions, though only one can be listed then, for syntax reasons.
xml-lint
Checks that the file is well-formed, but will not validate it against DTD or Schema.
About
Providence is both a reference to the "All-seeing eye of God" (As an atheist I simply needed to observe that on a lot of projects I've worked on in the past, someone who was watching over everything anyone did would have been quite useful. So I built me one.), in itself referenced in Hacker culture, and to H.P. Lovecraft (Who was born in Providence, Rhode Island and has the phrase "I AM PROVIDENCE" on his tombstone), the latter mostly because I hope this tool will help others shine a feeble light into the vast chaotic abysses of unnameable horrors lurking in the outer darkness of an uncaring (software) universe covered in the blood of Shub-Niggurath, the Black Goat with a Thousand Young, Ia ia, Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn...
Phew. Got a little carried away there ;-)
Acknowledgements
Heavily inspired by Netresearch, Chris Saylor, Peter van der Does and SensioLabs (where I do not have a paid account and so never had access to anything more than this publicly available list).