Manages git hooks inside a local git repository based on a configuration.
Have you ever wanted to integrate custom functionality into your code commit and push workflows without using IDE plugins, hacks, or gnarly scripts? We have, and that's why we developed Hookz
. Hookz
allows us to do a ton of commit tasks before our code even hits our branches. As you commit and push code to a git based source repository, Hookz will trigger scripts, run tasks, or do just about anything for you.
The best thing? Hookz
doesn't care what IDE you develop with, what your back end source control system is, or what languages you program in. Operating System? We don't care. We've compiled Hookz
for every OS and architecture you'd ever want.
Here's what happens when we use hookz
on Hookz
itself:
Git hooks are a great way to run supplemental commands as you interact with git. For deeper information, check out what git-scm has to say about git hooks
Hookz
generates scripts from a configuration that get triggered when interacting with git locally. For example, in a pre-commit you could lint your code, test it, and then add any modifications of files into the commit before pushing it to your remote. As seen in the screenshot above, tasks come back with a status.
Hookz
may return one of three different status codes as it executes the action pipeline:
Code | Description |
---|---|
PASS | The action has successfully completed |
WARN | An executable defined in the .hookz.yaml file wasn't found on the local system. In this case, the action is ignored and no attempt is made to run it. Flow will continue without an exit code of PASS or FAIL. |
FAIL | The action has failed. Execution stops. Consider this like a build break in a CI/CD pipeline that executes on a pull request. Errors must be addressed before the code is allowed to be committed. |
You can use Homebrew to install Hookz
using the following:
brew tap devops-kung-fu/homebrew-tap
brew install devops-kung-fu/homebrew-tap/hookz
The best way to install hookz
is via snap.
To install hookz
, download the latest release, extract the binary from the compressed file, make is executable, rename it to hookz
and toss it in your /usr/local/bin
directory for Linux, or on your path for other operating systems.
If you have a Go development environment set up, you can also simply do this:
go install github.com/devops-kung-fu/hookz@latest
If you'd like to contribute to the development of Hookz
then check out the Development section below.
Hookz uses a configuration file to generate hooks in your local git repository. This file needs to be in the root of your repository and must be named .hookz.yaml
version: 2.4.4
tools:
- tool: github.com/devops-kung-fu/lucha@latest
- tool: github.com/devops-kung-fu/hinge@latest
- tool: github.com/devops-kung-fu/gardener@latest
- tool: github.com/kisielk/errcheck@latest
- tool: golang.org/x/lint/golint@latest
- tool: github.com/fzipp/gocyclo/cmd/gocyclo@latest
hooks:
- type: pre-commit
actions:
- name: "PlantUML Image Generator"
exec: "gardener"
args: ["generate", "."]
- name: "Git Pull (Ensure there are no upstream changes)"
exec: git
args: ["pull"]
- name: "Go Tidy"
exec: go
args: ["mod", "tidy"]
- type: post-commit
actions:
- name: "Post Echo"
exec: echo
args: ["-e", "Done"]
- type: pre-push
actions:
- name: "Add all changed files during the pre-commit stage"
exec: git
args: ["add", "."]
Hookz will read this example configuration and create a pre-commit
hook and a post-commit
hook based on this yaml. It will also do a go install
on any source listed in the sources section of the yaml.
An action with an URL
will download the binary from the defined URL and configure the hook to execute the command with the defined arguments before a commit happens.
The post-commit in this configuration will execute a command named "dude
" with the arguments "Hello World"
after a commit has occurred. Note that the dude command must be on your path. If it isn't this post-commit will return a WARN message because the command isn't found.
Check out the tacklebox for a curated collection of actions to get you up and running quickly.
Quite often, downloadable binaries exist for multiple platforms when downloading. In order to get the right architecture for your current platform, Hookz v2.3.0
introduced dynamic architecture URL support. For example, hinge is available for multiple architectures such as linux
, darwin
(Mac), etc. By using the %%PLATFORM%%
tag in your URL to replace an architecture, the download functionality will retrieve the right binary for your current architecture.
You can use the following to retrieve the right architecture for hinge:
version: 2.4.4
hooks:
- type: pre-commit
actions:
- name: Hinge
url: https://github.com/devops-kung-fu/hinge/releases/download/v0.1.0/hinge-0.1.0-%%PLATFORM%%-amd64
args: ["."]
If you are running Hookz
on a Mac, this will bring down the hinge-0.1.0-darwin-amd64
binary, if on linux, the hinge-0.1.0-linux-amd64
binary will be downloaded.
You must have at least an URL, exec, or script defined in your actions. If you select one, then you shouldn't define the others in the YAML. Don't worry if you do, we have you covered and explain what happens in the following table.
Attribute | Notes |
---|---|
URL |
If this exists, then exec and script are ignored. The URL must be a link to an executable binary |
exec |
If this exists then URL and script are ignored |
script |
If this exists then URL, exec, and args are ignored |
args |
Optional in all cases |
Scripts can be embedded into the .hookz.yaml
in multiline format such as follows:
NOTE: There needs to be a \n at the end of a line if a multi-line statement exists in the script
node, and special characters need to be escaped properly.
- type: pre-commit
actions:
- name: "Go Tidy (Recursive)"
script: "
#!/bin/bash \n
echo -e Tidying all found go.mod occurrences \n
find . -name go.mod -print0 | xargs -0 -n1 dirname | xargs -L 1 bash -c 'cd \"$0\" && pwd && go mod tidy' \n
"
If you have args flags set, they can be referenced as $1, $2, etc. in your script in a similar manner as passing parameters in. Any scripting language is supported.
If multiple hooks are defined in the configuration with the same type (ie: pre-commit
) they will be configured to run in the order they appear in the file. There is no need to group types together, they will be written to the appropriate hooks.
Hook types that will execute are the same as supported by git. Examples are as follows:
applypatch-msg
commit-msg
fsmonitor-watchman
post-commit
post-update
pre-applypatch
pre-commit
pre-update
prepare-commit-msg
pre-push
pre-rebase
pre-receive
update
Any non-zero return code from a command executed in a hook will return a FAIL.
IMPORTANT: the URL
element will download a binary, store it in your .git/hookz folder and mark it executable. It is important to ensure that YOU KNOW THE SAFETY of the executable that you are downloading. A more secure way is to use the exec
attribute to run an application which is already locally installed, or embed a script in the script
element to download and check the shasum
of the file.
For additional security notes, view the SECURITY.md
To generate the hooks as defined in your configuration simply execute the following command in the root of your local repository where the .hookz.yaml
file resides:
hookz initialize # you can also use the init alias
Removing hooks can be done by executing the following command:
hookz remove
To re-download any file defined in an URL key:
hookz update
If there is a modification to the .hookz.yaml
file in your application, you'll need to apply the changes using the following:
hookz reset
The initialize
(init) and reset
command optionally take a debug flag to indicate extended output should be displayed while hookz
generates git hooks.
hookz init --debug
hookz reset --debug
If you want to see a log of what is happening when hookz
executes, use the --verbose
flag.
hookz init --verbose
hookz reset --verbose
Passing the --verbose-output
flag when running a hookz init
or hookz reset
command will trigger Hookz
to output extended information as git
executes the hooks during the commit, push, etc. process. All output from any action will be displayed during the commit/push process when this flag is used to build the hooks. This is handy for debugging or seeing errors that may be suppressed by hookz.
hookz init --verbose-output
hookz reset --verbose-output
We've assembled a collection of actions that you can lift into your .hookz.yaml
file to add functionality to your hooks and get up and running quickly.
Check out the collection here.
Assumes terraform
is in your PATH
for fmt
.
version: 2.4.4
hooks:
- type: pre-commit
actions:
- name: Terraform Format
exec: terraform
args: ["fmt"]
- name: Terraform Docs
url: https://github.com/terraform-docs/terraform-docs/releases/download/v0.12.1/terraform-docs-v0.12.1-%%PLATFORM%%-amd64
args: ["markdown", "table", "--output-file", "README.md", "."]
README.md
must contain the following tags where the documentation will be injected.
<!-- BEGIN_TF_DOCS -->
<!-- END_TF_DOCS -->
version: 2.4.4
hooks:
- type: pre-commit
actions:
- name: NPM CI
exec: npm
args: ["ci"]
- name: NPM Test
exec: npm
args: ["test"]
In order to use contribute and participate in the development of Hookz you'll need to have an updated Go environment. Before you start, please view the Contributing and Code of Conduct files in this repository.
This project makes use of DKFM tools such as Hookz and Hinge, as well as some other open source tooling. Install these tools with the following commands:
go install github.com/devops-kung-fu/hookz@latest
go install github.com/devops-kung-fu/lucha@latest
go install github.com/devops-kung-fu/hinge@latest
go install github.com/kisielk/errcheck@latest
go install golang.org/x/lint/golint@latest
go install github.com/fzipp/gocyclo@latest
Hookz
uses syft to generate a Software Bill of Materials every time a developer commits code to this repository.
The current CycloneDX SBoM for Hookz
is available here and the current SPDX SBoM for Hookz
is available here
A big thank-you to our friends at Freepik for the Hookz
logo.