diff --git a/.hookz.yaml b/.hookz.yaml index fb10528..5d0819b 100644 --- a/.hookz.yaml +++ b/.hookz.yaml @@ -11,15 +11,15 @@ 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 " - - name: "Go Build (Ensure pulled modules do not break the build)" - exec: go - args: ["build"] - name: "Update all go dependencies to latest" exec: go args: ["get", "-u", "./..."] - name: "Run gofmt to format the code" exec: gofmt args: ["-s", "-w", "**/*.go"] + - name: "Go Build (Ensure pulled modules do not break the build)" + exec: go + args: ["build", "-v"] - name: "Add all changed files during the pre-commit stage" exec: git args: ["add", "."] diff --git a/README.md b/README.md index c56b92a..aea0dad 100644 --- a/README.md +++ b/README.md @@ -20,23 +20,23 @@ Here's what happens when we use Hookz on Hookz itself: ## Installation -To install hookz, [download the latest release](https://github.com/devops-kung-fu/hookz/releases) , 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. +To install hookz, [download the latest release](https://github.com/devops-kung-fu/hookz/releases) , 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. Linux Example: ```bash -sudo chmod +x hookz-2.1.0-linux-amd64 -sudo mv hookz-2.1.0-linux-amd64 /usr/local/bin/hookz +sudo chmod +x hookz-2.1.1-linux-amd64 +sudo mv hookz-2.1.1-linux-amd64 /usr/local/bin/hookz ``` ## Configuration -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* +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``` ### Example Configuration ``` yaml -version: 2.1 +version: 2.1.1 hooks: - type: pre-commit actions: @@ -59,9 +59,9 @@ hooks: args: ["-e", "Done!"] ``` -Hooks will read this example configuration and create a pre-commit hook and a post-commit hook based on this yaml. +Hooks will read this example configuration and create a ```pre-commit``` hook and a ```post-commit``` hook based on this 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. +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 fail because the command isn't found. @@ -71,16 +71,16 @@ The following notes apply to the elements in the YAML: |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| +|```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| ### Inline scripting -Scripts can be embedded into the .hookz.yaml in multiline format such as follows: +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. +__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. ``` yaml - type: pre-commit @@ -96,35 +96,41 @@ If you have args flags set, they can be referenced as $1, $2, etc. in your scrip ### Support for multiple commands in a hook -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. +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 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 +* ```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``` ### Return Codes Any non-zero return code from a command executed in a hook will return a FAIL. +### Security + +**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](SECURITY.md) + ## Running Hookz ![](img/hookz.png) -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: +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: ``` bash hookz initialize # you can also use the init alias @@ -143,7 +149,7 @@ hookz update ``` ### Applying changes to the .hookz.yaml -If there is a modification to the .hookz.yaml file in your application, you'll need to apply the changes using the following: +If there is a modification to the ```.hookz.yaml``` file in your application, you'll need to apply the changes using the following: ``` bash hookz reset @@ -151,18 +157,20 @@ hookz reset ### Verbose option -The initialize (init) and reset command optionally take a verbosity flag to indicate extended output should be displayed when a hook executes. This is handy for debugging or seeing errors that may be suppressed by hookz. +The ```initialize``` (init) and ```reset``` command optionally take a verbosity flag to indicate extended output should be displayed when a hook executes. This is handy for debugging or seeing errors that may be suppressed by hookz. ``` hookz init --verbose hookz reset --verbose ``` + + ## Example Hooks ### Recursively tidy all go.mod files in subdirectories ```yaml -version: 2.1.0 +version: 2.1.1 hooks: - type: pre-commit actions: @@ -176,7 +184,7 @@ hooks: ### Update all go modules to the latest version before committing ```yaml -version: 2.1.0 +version: 2.1.1 hooks: - type: pre-commit actions: @@ -188,7 +196,7 @@ hooks: ### Pull from your remote branch before committing ``` yaml -version: 2.1.0 +version: 2.1.1 hooks: - type: pre-commit actions: @@ -196,6 +204,22 @@ hooks: exec: git args: ["pull"] ``` +### Check for open source component vulnerabilities +Requires [Sonatype Nancy](https://ossindex.sonatype.org/integration/nancy) + +__NOTE:__ The ```|| true``` on the end of the command makes the hook always return a success return code. If you want to break the commit on a failure, then remove this directive. + +```yaml +version: 2.1.1 +hooks: + - type: pre-commit + actions: + - name: Sonatype Nancy + script: " + #!/bin/bash \n + go list -json -m all | nancy sleuth || true \n + " +``` ### Terraform Format and Terraform Docs diff --git a/cmd/init.go b/cmd/init.go index 150b681..1192299 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -112,17 +112,13 @@ fi # This file was generated by Hookz # For more information, check out https://github.com/devops-kung-fu/hookz -# Built because Python sucks by The DevOps Kung Fu Masters (https://dkf.wtf) - reset='\033[0m' # Text Reset red='\033[41m' # Red green='\033[42m' # Green blackText='\033[0;30m' - - - ` +` filename, _ := filepath.Abs(fmt.Sprintf(".git/hooks/%s", hook.Type)) hookzFile, _ := filepath.Abs(fmt.Sprintf(".git/hooks/%s.hookz", hook.Type)) diff --git a/cmd/root.go b/cmd/root.go index fb0ad40..fa43b55 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -13,13 +13,14 @@ import ( "time" "github.com/cavaliercoder/grab" + "github.com/gookit/color" "github.com/spf13/cobra" "gopkg.in/yaml.v2" ) var ( //Verbose identifies if extended output should be configured during init and reset - Version = "2.1.0" + Version = "2.1.1" Verbose bool rootCmd = &cobra.Command{ Use: "hookz", @@ -56,17 +57,23 @@ func readConfig() (config Configuration, err error) { if err != nil { return } + + if config.Version == "" { + err = errors.New("no configuration version value found in .hookz.yaml") + return + } + // Check version ver := strings.Split(config.Version, ".") verMatch := strings.Split(Version, ".") if fmt.Sprintf("%v.%v", ver[0], ver[1]) != fmt.Sprintf("%v.%v", verMatch[0], verMatch[1]) { - err = errors.New(fmt.Sprintf("Version Mismatch: Expected v%v.%v - Check your .hookz.yaml configuration\n", verMatch[0], verMatch[1])) + err = fmt.Errorf("version mismatch: Expected v%v.%v - Check your .hookz.yaml configuration", verMatch[0], verMatch[1]) } return } func hookzHeader() { - fmt.Println("Hookz") + color.Style{color.FgWhite, color.OpBold}.Println("Hookz") fmt.Println("https://github.com/devops-kung-fu/hookz") fmt.Printf("Version: %s\n", Version) fmt.Println("") diff --git a/go.mod b/go.mod index 691503d..396a83a 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,9 @@ go 1.16 require ( github.com/cavaliercoder/grab v2.0.0+incompatible + github.com/gookit/color v1.4.2 github.com/segmentio/ksuid v1.0.3 github.com/spf13/cobra v1.1.3 + golang.org/x/sys v0.0.0-20210426080607-c94f62235c83 // indirect gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index 393e1b4..b2c4737 100644 --- a/go.sum +++ b/go.sum @@ -34,6 +34,7 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -65,6 +66,8 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk= +github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -127,6 +130,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -164,9 +168,13 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -231,6 +239,9 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426080607-c94f62235c83 h1:kHSDPqCtsHZOg0nVylfTo20DDhE9gG4Y0jn7hKQ0QAM= +golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -287,6 +298,8 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=