├── run-go-vet.sh ├── run-go-err-check.sh ├── run-go-gofumpt.sh ├── run-go-fmt-import.sh ├── run-go-imports-reviser.sh ├── run-go-lint.sh ├── run-go-unit-tests.sh ├── .pre-commit-config.yaml ├── run-golangci-lint.sh ├── run-go-ruleguard.sh ├── .github └── workflows │ └── lint.yml ├── LICENSE ├── run-go-static-check.sh ├── README.md └── .pre-commit-hooks.yaml /run-go-vet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for DIR in $(echo "$@"|xargs -n1 dirname|sort -u); do 4 | go vet ./"$DIR" 5 | done 6 | -------------------------------------------------------------------------------- /run-go-err-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for DIR in $(echo "$@"|xargs -n1 dirname|sort -u); do 4 | errcheck ./"$DIR" 5 | done 6 | -------------------------------------------------------------------------------- /run-go-gofumpt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | LIST_OF_FILES=$(gofumpt -l -w "$@") 4 | # print a list of affected files if any 5 | echo "$LIST_OF_FILES" 6 | if [ -n "$LIST_OF_FILES" ];then 7 | exit 1 8 | fi 9 | -------------------------------------------------------------------------------- /run-go-fmt-import.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | LIST_OF_FILES=$(goimports -l -w "$@") 4 | # print a list of affected files if any 5 | echo "$LIST_OF_FILES" 6 | if [ -n "$LIST_OF_FILES" ];then 7 | exit 1 8 | fi 9 | -------------------------------------------------------------------------------- /run-go-imports-reviser.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | LIST_OF_FILES=$(goimports-reviser -rm-unused -format "$@") 4 | # print a list of affected files if any 5 | echo "$LIST_OF_FILES" 6 | if [ -n "$LIST_OF_FILES" ];then 7 | exit 1 8 | fi -------------------------------------------------------------------------------- /run-go-lint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PASS=true 4 | for FILE in "$@" 5 | do 6 | golint -set_exit_status "$FILE" 7 | if [ "$?" -eq 1 ]; then 8 | PASS=false 9 | fi 10 | done 11 | 12 | if [ "$PASS" = "false" ]; then 13 | exit 1 14 | fi -------------------------------------------------------------------------------- /run-go-unit-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PASS=true 4 | for DIR in $(echo "$@"|xargs -n1 dirname|sort -u); do 5 | go test ./"$DIR" 6 | if [ "$?" -eq 1 ]; then 7 | PASS=false 8 | fi 9 | done 10 | 11 | if [ "$PASS" = "false" ]; then 12 | exit 1 13 | fi -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.3.0 4 | hooks: 5 | - id: trailing-whitespace 6 | - id: check-yaml 7 | - id: check-json 8 | - id: end-of-file-fixer 9 | - repo: https://github.com/koalaman/shellcheck-precommit 10 | rev: v0.8.0 11 | hooks: 12 | - id: shellcheck 13 | -------------------------------------------------------------------------------- /run-golangci-lint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CONFIG_FILE="$1" 4 | 5 | if ! command -v golangci-lint 2>&1 /dev/null 6 | then 7 | echo "golangci-lint could not be found" 8 | exit 9 | fi 10 | 11 | ERRS=$(golangci-lint run --new-from-rev="$(git rev-parse HEAD)" "$CONFIG_FILE") 12 | 13 | if [ -n "${ERRS}" ]; then 14 | echo "${ERRS}" 15 | exit 1 16 | fi 17 | exit 0 18 | -------------------------------------------------------------------------------- /run-go-ruleguard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | RULE_FILE="$1" 4 | 5 | if ! command -v ruleguard 2>&1 /dev/null 6 | then 7 | echo "go-ruleguard could not be found" 8 | exit 9 | fi 10 | 11 | PASS=true 12 | 13 | for FILE in "$@" 14 | do 15 | 16 | if ! ruleguard -c 0 -rules "$RULE_FILE" "$FILE"; 17 | then 18 | PASS=false 19 | fi 20 | done 21 | 22 | if [ "$PASS" = "false" ]; then 23 | exit 1 24 | fi 25 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | lint: 8 | runs-on: ubuntu-latest 9 | steps: 10 | # 1) Check out the code 11 | - name: Check out repository 12 | uses: actions/checkout@v3 13 | 14 | # 2) Install and run ShellCheck on *.sh 15 | - name: Install ShellCheck 16 | run: | 17 | sudo apt-get update 18 | sudo apt-get install -y shellcheck 19 | - name: Run ShellCheck 20 | run: | 21 | shellcheck ./*.sh 22 | 23 | # 3) Install Node and run markdownlint on *.md 24 | - name: Setup Node 25 | uses: actions/setup-node@v3 26 | with: 27 | node-version: 16 28 | 29 | - name: Install markdownlint-cli 30 | run: npm install -g markdownlint-cli 31 | 32 | - name: Run markdownlint 33 | run: | 34 | markdownlint ./**/*.md 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | MIT License 3 | 4 | Copyright (c) 2018 Bahjat Al Mostafa < twitter @bahjat> 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. -------------------------------------------------------------------------------- /run-go-static-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | cmd_options=() 6 | file_args=() 7 | 8 | # we parse out cli options and file arguments 9 | # technically we allow for options to be passed after the file arguments, but 10 | # we know that pre-commit puts the file arguments last 11 | # also, we do not handle file names starting with a hyphen 12 | while [[ $# -gt 0 ]]; do 13 | if [[ "$1" == -* ]]; then 14 | # If it's an option, ensure there's a value after it 15 | if [[ $# -ge 2 && -n "$2" && "$2" != -* ]]; then 16 | cmd_options+=("$1" "$2") 17 | shift 2 18 | else 19 | echo "Error: Missing value for key $1" 20 | exit 1 21 | fi 22 | else 23 | file_args+=("$1") 24 | shift 25 | fi 26 | done 27 | 28 | if [[ ${#file_args[@]} -eq 0 ]]; then 29 | echo "Error: No file arguments provided" 30 | exit 1 31 | fi 32 | 33 | packages=() 34 | 35 | for DIR in $(echo "${file_args[@]}" | xargs -n1 dirname | sort -u); do 36 | packages+=("$DIR") 37 | done 38 | 39 | [[ ${#cmd_options[@]} -eq 0 ]] && cmd_options+=("") 40 | 41 | for package in "${packages[@]}"; do 42 | staticcheck "${cmd_options[@]}" ./"${package}" 43 | done 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pre-commit-golang 2 | 3 | Golang pre-commit hooks for [pre-commit.com](http://pre-commit.com/) 4 | 5 | ## Installation 6 | 7 | You first need to install [pre-commit](https://pre-commit.com/#install): 8 | 9 | ```bash 10 | brew install pre-commit 11 | ``` 12 | 13 | Then install pre-commit in your Git repository: 14 | 15 | ```bash 16 | pre-commit install 17 | ``` 18 | 19 | ## Usage 20 | 21 | Add a file named `.pre-commit-config.yaml` to the root directory of your repository: 22 | 23 | ```yaml 24 | repos: 25 | - repo: https://github.com/Bahjat/pre-commit-golang 26 | rev: v1.0.5 27 | hooks: 28 | - id: go-fmt-import 29 | - id: go-vet 30 | - id: go-lint 31 | - id: go-unit-tests 32 | - id: gofumpt # requires github.com/mvdan/gofumpt 33 | - id: go-err-check # requires github.com/kisielk/errcheck 34 | - id: go-static-check # install https://staticcheck.io/docs/ 35 | - id: golangci-lint # requires github.com/golangci/golangci-lint 36 | args: [--config=.github/linters/.golangci.yml] # optional 37 | - id: go-ruleguard # requires https://github.com/quasilyte/go-ruleguard 38 | args: [rules/rules.go] 39 | - id: go-imports-reviser # requires https://github.com/incu6us/goimports-reviser 40 | ``` 41 | 42 | ## Contributing 43 | 44 | - Fork it 45 | - Create your feature branch: `git checkout -b my-new-feature` 46 | - Commit your changes: `git commit -am 'Add some feature'` 47 | - Push to the branch: `git push origin my-new-feature` 48 | - Create a new Pull Request 49 | 50 | ## Credits 51 | 52 | This repository is inspired by [dnephin/pre-commit-golang](https://github.com/dnephin/pre-commit-golang). 53 | 54 | ## Finally 55 | 56 | If you like these hooks, please give this repository a star! 57 | -------------------------------------------------------------------------------- /.pre-commit-hooks.yaml: -------------------------------------------------------------------------------- 1 | - id: go-fmt-import 2 | name: "go import/fmt" 3 | entry: run-go-fmt-import.sh 4 | files: '\.go$' 5 | language: "script" 6 | description: "Runs `goimport,gofmt`, requires golang" 7 | 8 | - id: go-vet 9 | name: "go vet" 10 | entry: run-go-vet.sh 11 | files: '\.go$' 12 | language: "script" 13 | description: "Runs `go vet`, requires golang" 14 | 15 | - id: go-lint 16 | name: "golint" 17 | entry: run-go-lint.sh 18 | files: '\.go$' 19 | language: "script" 20 | description: "Runs `go lint`, requires golang" 21 | 22 | - id: go-unit-tests 23 | name: "go unit test" 24 | entry: run-go-unit-tests.sh 25 | files: '\.go$' 26 | language: "script" 27 | description: "Runs `go test`, requires golang" 28 | 29 | - id: gofumpt 30 | name: "gofumpt" 31 | entry: run-go-gofumpt.sh 32 | files: '\.go$' 33 | language: "script" 34 | description: "Runs `gofumpt`, requires github.com/mvdan/gofumpt" 35 | 36 | - id: go-err-check 37 | name: "go errcheck" 38 | entry: run-go-err-check.sh 39 | files: '\.go$' 40 | language: "script" 41 | description: "Runs `errcheck`, requires github.com/kisielk/errcheck" 42 | 43 | - id: go-static-check 44 | name: "go staticcheck" 45 | entry: run-go-static-check.sh 46 | files: '\.go$' 47 | language: "script" 48 | description: "Runs `staticcheck`, install https://staticcheck.io/docs/" 49 | require_serial: true 50 | 51 | - id: golangci-lint 52 | name: "go golangci-lint" 53 | entry: run-golangci-lint.sh 54 | files: '\.go$' 55 | language: "script" 56 | description: "Runs `golangci-lint`, install https://github.com/golangci/golangci-lint" 57 | 58 | - id: go-ruleguard 59 | name: "go-ruleguard" 60 | entry: run-go-ruleguard.sh 61 | files: '\.go$' 62 | language: "script" 63 | description: "Runs `go-ruleguard`, install https://github.com/quasilyte/go-ruleguard" 64 | 65 | - id: go-imports-reviser 66 | name: "go-imports-reviser" 67 | entry: run-go-imports-reviser.sh 68 | files: '\.go$' 69 | language: "script" 70 | description: "Runs `goimports-reviser`, install https://github.com/incu6us/goimports-reviser" 71 | --------------------------------------------------------------------------------