CircleCI + ShellCheck でシェルスクリプトを静的解析する

シェルスクリプトのレビューを効率化するため,シェルスクリプト専用の静的解析ツール "ShellCheck" を導入して,さらに CircleCI で自動テストすることにした.導入検証も兼ねて,個人的に使ってる dotfiles に導入してみた話をまとめる.

github.com

apt-get install shellcheck はできなかった

CircleCI で稼働するコンテナは "Ubuntu 12.04 (Precise)" or "Ubuntu 14.04 (Trusty)" なので,README に書いてある通り apt-get install shellcheckcircle.yml に書いて実行したら,エラーになってしまった.apt-get update も効果は無かった.

$ sudo apt-get install shellcheck
Reading package lists... Done


Building dependency tree       


Reading state information... Done

E: Unable to locate package shellcheck

sudo apt-get install shellcheck returned exit code 100

Action failed: sudo apt-get install shellcheck

Issue を確認したら「Cabal を試してみて!」や「Ubuntu 用にパッケージングするのは良いけど,手伝ってくれる人はいる?」といったコメントがポストされていたけど,その後の進展は無くて,現時点だと難しそうだな...と判断した.

github.com

github.com

Cabal を使って ShellCheck をインストールした

よって,Cabal を使うことにした.CircleCI だとデフォルトで Cabal がインストールされていて,特に意識する必要は無かった.

circleci.com

f:id:kakku22:20170105003602p:plain

しかし,Cabal 経由で ShellCheck でインストールすると,遅すぎる問題があった.以下のログを見るとわかる通り,8分も実行したままになってしまう...!回避策としては ~/.cabalcache_directories に設定して,コンテナ起動時にリストアできるようにし,既にインストールされている場合はスキップするようにした.

f:id:kakku22:20170105003858p:plain

ドキュメントを見ると Cabal はデフォルトで cache_directories の対象になっているようにも読み取れるけど,今回は明示的に書くことにした.

circleci.com

完成した circle.yml

machine:
  environment:
    PATH: ${HOME}/.cabal/bin/:${PATH}

dependencies:
  cache_directories:
    - "~/.cabal"
  post:
    - cabal --version
    - cabal update
    - if ! type shellcheck > /dev/null; then cabal install ShellCheck; fi
    - shellcheck --version

test:
  override:
    - shellcheck --exclude=SC2039 *.sh

github.com

静的解析エラーを検出できるようになった

shellcheck にパスを通す前に動かしたキャプチャだから絶対パスになっている)

f:id:kakku22:20170105170240p:plain

CircleCI Feature Requests

ShellCheck をデフォルトで使えるようにして!とリクエストは出ていた.

discuss.circleci.com

まとめ

  • シェルスクリプトだって CI で静的解析エラーを検知したい
  • ShellCheck 便利(ルールが厳しすぎるけど...w)
  • CircleCI で動かす場合は Cabal 経由でインストールすると良い(cache_directories も必ず使うこと)