Go Conference Fukuoka 2019から刺激を受けてanalysis toolを作った
はじめに
先週Go Conferenceに参加させてもらいました。そこで良い刺激をもらい、その勢いでtoolを作ったのでblogに残しておこうと思います
Go Conference'19 Summer in Fukuoka - Go Conference'19 Summer in Fukuoka
聞いたセッション
たくさんのセッションを聞かせてもらった。がタイトルの通りその中でもより良い刺激を受けたセッションが下記です
Go Conference'19 Summer in Fukuokaで登壇してきた | おそらくはそれさえも平凡な日々
このセッションを聞いて、よし自分もanalysis tool作ろうっと思った
作ったtool
どんなtoolか?
go fileのimport Pathを抽出して、あらかじめ定義した依存ルールに違反をしていないかを静的解析するツールです
会社のプロダクトでCleanArchitectureを採用しているものがあります。そのArchitectureの一つのポイントがDIP(Dependency Inversion Principle) = 依存関係逆転の原則 というものがあります。
このルールにちゃんと則っているかのチェックが、go fileのimport部分を見れば簡単にチェックができると思ったので作りました
しかし、実はこの手のツールは既にありました。
↓
最初はこのツールを使っていました。が、下記の不満点が自分の中で出てきました
感じた課題感
golang.org/x/tools/go/analysis
を使ったらもっと簡単にできるなぁ- プロジェクトによってレイヤー名が異なるのでその辺はそれぞれにconfigで可変できるようになると使いやすいなぁ
- このツールでは決めうちされていた
- それぞれのレイヤーでディレクトリを掘っていくとpackage名が必ずしもレイヤー名とならない場合があって、その場合困った
├── infrastructures │ ├── a │ │ ├── b.go
上記の場合、bというファイルのpackage名はa
としている場合とinfrastructures
としている場合があると思う。前者のパターンにしている場合、このツールではうまく解析ができなかった
- 自分で作ったパッケージの依存関係はチェックできるけど、ビルドインのパッケージ、サードパーティーのパッケージの依存のチェックはできなかった。
- CleanArchitectureだとexternalレイヤー以外では外のpackageのimportは禁止されてるけど、そのチェックができていない
- 例えば、CleanArchitectureでいうinterfaces層からビルドインパッケージのimportの良し悪し。domain層からのビルドインパッケージのimportの良し悪し。等はおそらくチームの規約を決めて運用する必要があるが、その辺りも規約をカスタムしてチェックしたいなーと思っていた
モチベーション
上記の課題感を自分で解決してみようと思い、勉強がてら作った
話を戻して今回作ったtool(dependency-check)はどういう風に使うのか
readmeにも色々書いたが改めて。
1. まずはinstallしてください
go get github.com/nakamura244/dependency-check
2. configを配置します
pathはどこでも大丈夫ですが、外部のCIツールでも活用する場合は、該当のレポジトリ内に設置する方が良いかと思います
ex:
base: innerPath: &innerPath github.com/xxx/xxx # チェックをしたいレポジトリのパスを記載 layer1: layerName: infrastructures # レイヤー名を任意でつけます packageNames: - github.com/xxx/xxx/infrastructures # layerNameに属するパッケージ名をパスから記載(複数設定可能) innerPath: *innerPath # エイリアス allowDependPackages: # 依存して良い(import可)パッケージ名をパスから記載(複数設定可能)。ただし同じリポジトリ内のパッケージに限る。nullの場合は同リポジトリ内のパッケージの依存を許さないという設定になる - github.com/xxx/xxx/domain - github.com/xxx/xxx/interfaces - github.com/xxx/xxx/config - github.com/xxx/xxx/infrastructures/iface allowDependBuildIn: yes # infrastructuresレイヤーはgoのbuildinパッケージに依存しても良い(import可)かどうかの設定。値は`yes` or `no` allowDependOutside: yes # infrastructuresレイヤーはgoの外部のパッケージに依存しても良い(import可)かどうかの設定。値は`yes` or `no`
上記はlayer1の設定ですが、layer4まで設定可能です
下記のexampleを見てもらっても良いかと思います
3. Run
実行したいリポジトリに移動して下記のコマンドを実行
dependency-check -ignoreTests=true -config=./.dependency-check/config.yml ./...
-ignoreTests=true
はtestファイルは無視するかどうかの設定-config=./.dependency-check/config.yml
は2で作成したconfig yamlのパスを設定./...
は再帰的に解析したいパス
4. Result
失敗した時はexit status 1
で終了します。
出力は成功の場合、失敗の場合は下記のように標準出力されます https://github.com/nakamura244/dependency-check/blob/master/README.md#run
注意!!
CircleCIで組み込んで利用する場合、environment
でGOROOT
を指定しないと期待値通りに動きません。自分の環境下ではそうでしたというだけかもしれないけど
https://github.com/nakamura244/dependency-check/blob/master/.circleci/config.yml#L63
https://github.com/nakamura244/dependency-check/blob/master/README.md#caution
実際に会社のプロダクトに適用してみた
CircleCIを使っていてそのJOBの一つに加えました
workflowの一部にdepcというjobを追加して、dependency-checkを実施しています。このjobがfaildすると次のjob(deploy)ができない感じになっています
最後に
運営の方々には良い機会を提供いただき感謝しかありません。お疲れ様でした。
やっぱり実際に足を運んで、技術に触れる事は成長につながるなーと改めて思いました。
おまけ
スペシャルゲストで福岡市長が来てくれました。政治家ってプレゼンテーションが超絶うまいんだなーと体験しました
福岡市長高島宗一郎 GO conference'19 summer in fukuokaに出席しました - YouTube