GoでGitHubへpushする前にmakeコマンドでprecommitする方法


### はじめに

:::note warn
こちらはzennの記事の転載となります。
:::

平下CTO@sweeepです。Go言語でGitHubなどへpushする前にmakeコマンドでprecommitをする方法をこちらをサンプルに解説します。→ [GoでファイルのValidation方法など](https://zenn.dev/hirac/articles/dc537f0786cae9)

本記事の内容です。
* precommitの内容
* makeコマンドでprecommit一括実行
* 実行結果
* PR時のprecommit checkリスト

### precommitの内容
precommit時のそれぞれの整形/linter/チェックについて以下記します。

* goimports: Go言語の標準パッケージでパッケージのインポートを整形し、また、gofmtのルールでコードを整形します。
```
$ find . -print | grep --regex '.*\.go' | xargs goimports -w -local "github.com/hirac1220/go-file/utils"
```

* fmt: Go言語の標準パッケージでコードを整形します。
```
$ go fmt ./...
```

* vet: Go言語標準パッケージで静的解析します。
```
$ go vet ./...
```

* errcheck: エラーハンドリングされていないエラーをチェックします。
```
$ errcheck
```

https://github.com/kisielk/errcheck

* staticcheck: こちらもGo言語を静的解析します。
```
$ staticcheck ./...
```

https://staticcheck.io/docs/getting-started/

* gosec: ソースコードをスキャンして、セキュリティの問題についてチェックします。
```
$ gosec ./...
```

https://github.com/securego/gosec

* golangci-lint: Go言語の多くのlinterを搭載しています。こちらで他のlinterまかなうことも。
```
$ golangci-lint run ./...
```

https://github.com/golangci/golangci-lint

* それぞれインストール
それぞれのパッケージのインストールコマンドです。必要に応じてインストール実施してください。
```
$ go install golang.org/x/tools/cmd/goimports@latest
$ go install github.com/kisielk/errcheck@latest
$ go install honnef.co/go/tools/cmd/staticcheck@latest
$ brew install golangci-lint
$ brew upgrade golangci-lint
$ curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s -- -b $(GOPATH)/bin latest
```

makeコマンドにしてあるので、一括インストールも可能です。
```
$ cd utils/file
$ make install
```


### makeコマンドでprecommit一括実行
GitHubへpushする前にmakeコマンドで下記precommitを一括実施します。hookして自動でprecommitをかけることも可能ですが、Draft PRなどでとりあえずのpushしたいこともあり、マニュアル運用としています（自動化はGitHub側のreviewdogなど導入予定）。

以下がMakefileの定義となります。
```makefile:utils/file/Makefile
# precommit check
precommit: goimports fmt errcheck staticcheck gosec

goimports:
	find . -print | grep --regex '.*\.go' | xargs goimports -w -local "github.com/hirac1220/go-file/utils"

fmt:
	go fmt ./...

vet:
	go vet ./...

errcheck:
	errcheck

staticcheck:
	staticcheck ./...

golangci:
	golangci-lint run ./...

gosec:
	gosec ./...
```

### precommit実行結果

以下makeコマンドで実行します。
```
$ cd utils/file
$ make precommit
```

precommit実行結果は以下のようになります。

```
$ make precommit
find . -print | grep --regex '.*\.go' | xargs goimports -w -local "github.com/hirac1220/go-file/utils"
go fmt ./...
errcheck
staticcheck ./...
gosec ./...
[gosec] 2022/03/21 18:32:15 Including rules: default
[gosec] 2022/03/21 18:32:15 Excluding rules: default
[gosec] 2022/03/21 18:32:15 Import directory: /Users/kimi/go/src/github.com/hirac1220/go/go-file-validate/utils/file
[gosec] 2022/03/21 18:32:16 Checking package: file
[gosec] 2022/03/21 18:32:16 Checking file: /Users/kimi/go/src/github.com/hirac1220/go/go-file-validate/utils/file/file.go
Results:


Summary:
  Gosec  : 2.9.3
  Files  : 1
  Lines  : 66
  Nosec  : 0
  Issues : 0

```

### PR時のprecommit checkリスト
プルリクエストテンプレートをリポジトリのルートディレクトリで作成し、PR時にprecommit実施したかチェックするようにします。
添付のように、リポジトリのcreate new fileで.github/pull_request_template.mdを作成し、以下を記入します。

```
### レビュー前チェック
- [ ] make precommit

```

![pr_template.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241917/7e424e1f-e70d-d42a-e63c-64ad52aae2f6.png)


https://docs.github.com/ja/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository

PR実施すると添付のようにprecommitチェックリストが表示されます。

![pr_check.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241917/dac3c83d-a560-351e-1814-434670f16b77.png)


### まとめ
今回はGo言語でのGitHubなどへpushする前にmakeコマンドでprecommitをする方法を解説しました。今後はprecommitと同等の設定をしたreviewdogなど導入し、precommitせずにPRすると自動でコメントしてもらうようにしていきたいです。

https://github.com/reviewdog/reviewdog

今回使用したサンプルはこちらのGitHubレポジトリにあります。

https://github.com/hirac1220/go-file-validate

ここまで読んでいただきありがとうございました！