可搬性の高いGoのVendoring環境整備

GAE/Goでも、package main/func mainのGoでも、プロジェクトはdirenvをつかってVendoringを実現すると可搬性高くて最高というメモ。

direnv

シェルの実行パスに置かれたローカル設定を動的に反映させてくれるかしこいツール。素敵。インストールはHomeBrewで可能。マメとしてはGoで書かれてます。

http://direnv.net/

.bash_profile

# ~/.bash_profile
eval "$(direnv hook bash)"

direnvでシェルを監視します。私はmacOSbashなので上記のとおり。

.envrc

コントロールしたいフォルダに.envrcって名前の設定ファイルを置く。今はこんなの書いています。書いて配置したあと、一回はコンソールでフォルダにはいって、$ direnv allow って打たないといけない。

# ~/Projects/bookreader/.envrc
export GOPATH=$PWD/vendor:$PWD
# export PATH=$PWD/vendor/bin:$PWD/bin:$PATH

GOPATHは最初に、./vendor で次に ./ と二つをこの順番で通す。PATHはそれぞれのbinだけどGAEだと ./binはでてこないし、私の使い方では ./vendorの下にもbinがでてきたことない。gofmtとかgoimportとかビルド時ツールがプロジェクト内で管理されてたりすると必要かな。

# ~/Projects/.envrc
export PATH=~/go_appengine_sdk:$PATH

GAE SDKのパス設定は適宜上位フォルダに.envrcを置いて通している。フォルダツリーに従ってちゃんと.envrcの設定がカスケードされる。こうすると、ローカルPCで動かすGoとGAE/Go向けGoとクロスコンパイルするGoとで同じPCかつ同じIDEを使い分けるのも簡単。

プロジェクトのフォルダ構成(GAE版)

$ tree -a -L 3 ./Projects/bookreader/
./Projects/bookreader/
├── .envrc
├── .idea
├── src
│   ├── app.go
│   ├── app.yaml
│   ├── book
│   │   ├── book.go
│   │   └── book_test.go
│   └── public
│       └── js
└── vendor
    ├── pkg
    │   └── darwin_amd64_appengine
    └── src
        ├── goji.io
        └── golang.org

こんな感じ。GOPATHはプロジェクトのルートより優先でvendorフォルダを指定しているので、goapp getでもgo getでもvendorフォルダに格納されて自分のコードと混在しない。gbとかの専用Vendoringツールが必要なく綺麗。GAEのyamlファイルはルートにおいていないのでvendorの中はリンクされるものだけを取ってくるので、GAE的に危険なコードがはいってても(アプリのソースから使わなければ)問題ない。

WebStormの設定

f:id:masataka_k:20161029080135p:plain

direnvが動的に設定するからなのか、まだ何か研究が足りないのか、WebStormのほうではライブラリパスを明示的に追加しないとうまくなかった。この設定をするとコード補完からビルドやデバッグまでALL OK。

ちなみにapp.yaml

version: 1
runtime: go
api_version: go1
handlers:
- url: /(.*\.(css|ttf|gif|png|jpg|js))$
  static_files: public/\1
  upload: public/.*\.(css|ttf|gif|png|jpg|js)$
- url: /.*
  script: _go_app

省略したけど、実際のプロジェクトでは同じプロジェクト内にreact + redux + material-uiのクライアントアプリもあって、gulpによるビルドで/src/public/jsの下にコピーしてきています。

react, react-router, redux, react-redux, react-router-redux, redux-actions, redux-form, material-ui, redux-form-material-ui, axiosというスタック。開発はbabel, eslint, jasmine, browserifyで。それぞれよくできている。