Configuration

If you look at a captainhook.json configuration, it consists of a config block for each hook and an optional config section to tweak some setting.

{
  "commit-msg": {
    // a hook config block
  },
  "pre-commit": {
    // another hook config block
  },
  // ...
}

Hook Config

Each hook configuration consists of two things an on/off switch and a list of actions to execute.

'commit-msg': {
  "enabled": true,
  "actions": []
}

By setting enabled to false, CaptainHook will not execute the configured actions even if the hook is triggered by git.

Actions

CLI commands

Actions can be two things, firstly you can run any cli command, as long as it uses exit codes to notify the caller about its success. If you, for example, run PHPUnit and a test fails, it will exit with status code 1, so CaptainHook knows that it should stop the currently running git command with an error.

{
  "pre-commit": {
    "enabled": true,
    "actions": [
      {
        "action": "phpunit.phar --configuration=phpunit.git.xml"
      }
    ]
  }
}

Using the example above in a pre-commit hook will prevent you from committing code that breaks any unit test.

PHP scripts

Secondly you can execute any PHP class implementing an interfaces defined by CaptainHook. The interface you have to implement is \CaptainHook\App\Hook\Action. CaptainHook comes with some built-in, basic validation classes. So let's have a look at how to configure those.

{
  "commit-msg": {
    "enabled": true,
    "actions": [
      {
        "action": "\CaptainHook\App\Hook\Message\Action\Regex",
        "options": {
          "regex": "#.*#"
        }
      }
    ]
  }
}

With this configuration you can validate your commit messages against a regular expression. If your commit message doesn't match your regular expression your commit fails.

Here's a list of all built-in actions

Commit-Message
Pre-Commit

You can easily build your own action classes. Have a look on how to extend CaptainHook.

Conditions

You can add conditions to an action configuration. Only if all configured conditions apply the action gets executed. This becomes useful for example if you want to run composer install automatically every time someone changes composer.json or composer.lock.

To make sure you catch every change in your repository you have to add the action to both post-merge and post-checkout hooks. This way you run composer after every merge or pull or after checking out another branch that changes you local composer files.

{
  "post-merge": {
    "enabled": true,
    "actions": [
      {
        "action": "composer install",
        "options": {},
        "conditions": [
          {
            "exec": "\\CaptainHook\\App\Hook\\Condition\\FileChange\\Any",
            "args": [
              ["composer.json", "composer.lock"]
            ]
          }
        ]
      }
    ]
  },
  "post-checkout": {
    "enabled": true,
    "actions": [
      {
        "action": "composer install",
        "options": {},
        "conditions": [
          {
            "exec": "\\CaptainHook\\App\Hook\\Condition\\FileChange\\Any",
            "args": [
              ["composer.json", "composer.lock"]
            ]
          }
        ]
      }
    ]
  }
}

Here's a list of all built-in conditions

post-merge / post-checkout

You can build your own conditions. You can either use simple scripts or binaries which have to return an exit code. The exit code 0 means the condition applies, any exit code other then 0 means the condition does not apply.

Or you can build custom PHP Conditions. For an exact guide have a look at the "how to extend CaptainHook" section.

Include other configuration files

If you have a lot of projects you maybe want to define a set of default hooks for all of them. To maintain such a default configuration CaptainHook version 4.4.0 introduced the possibility to include other CaptainHook configurations like this.

{
  "config": {
    "includes": [
      "some-other-captainhook-config.json"
    ]
  },
  "pre-commit": {
    "enabled": true,
    "actions": [
      {
        "action"0: "\CaptainHook\App\Hook\Message\Action\Regex",
        "options": {
          "regex": "#.*#"
        }
      }
    ]
  }
}

The idea is to create a separate composer package e.g. my-git-hooks that is structured like this.

my-git-hooks/
├── composer.json
├── msg-validation.json
└── crazy-workflow.json

Inside your composer.json you require all libs and plugins you need to execute the configured actions plus captainhook/captainhook or captainhook/plugin-composer. The only thing you have to do in your projects is to require your my-git-hooks package and add something like this to your local project captainhook.json file.

{
  "config": {
    "includes": [
      "vendor/my-company/my-git-hooks/msg-validation.json",
      "vendor/my-company/my-git-hooks/crazy-workflow.json"
    ]
  }
}

To update the base configuration you create a new version for your my-git-hooks package and run composer update in your projects.

Include Level

By default you can't include configurations in included configurations. But if you really want to shoot yourself in the foot, who am I to judge you. You can increase the maximum levels of inclusion in your project configuration. Be aware, that setting this in any included configuration will have no effect.

{
  "config": {
    "includes-level": 2,
    "includes": [
      "vendor/my-company/my-git-hooks/msg-validation.json",
      "vendor/my-company/my-git-hooks/crazy-workflow.json"
    ]
  }
}

Settings

For example if your .git directory is not located on the same level as your captainhook.json.

{
  "config": {
    "git-directory": "../../.git",
    "verbosity": "verbose",
    "ansi-colors": false,
    "includes-level": 2,
    "includes": [],
    "run-mode": "docker",
    "run-exec": "docker exec CONTAINER_NAME"
  }
}
Setting Description Default
git-directory Custom path to your repositories .git directory (relative from the configuration file) .git
verbosity Define the output verbosity [quiet|normal|verbose|debug] verbose
ansi-colors Enable or disable ANSI color output true
includes A list of CaptainHook configuration files to include -
includes-level Nesting level of allowed config file inclusion 0
run-mode CaptainHook execution mode (local|docker) local
run-exec Docker command to spin up the container and execute a script -