ZOZOテクノロジーズのむーさん@murs313です。
WEARが大好きで入社し、今はWEARのwebアプリの開発をしています。
WEARは今年のハロウィンで7才になりました。
歳を重ね、様々な人がコードを書き、コーディング規約や自動チェックがなく、WEARのコードはこのような状態になっていました…。
ほげえええええええ!! インデント!!!インデントォォ!!!
ファイルによって改行コードも違うやないか…!!なんてこった\(^o^)/
このままでは気になってコードが書けない…。私はコーディングスタイルを統一する決意をしたのでした。
しかし、弊プロジェクトは手動デプロイで、機械的にスタイルを揃えたとしてもまとめてリリースすることは難しい状況でした。
なので、編集・新規作成したファイルのみを対象にして、コーディングスタイルを無理なく整えていくことにしました。
まずは書き方の振れ幅が大きいJavaScriptを対象にして、ESLintを導入することにしました。
ゴール
- CircleCIでESLintによるJSファイルのコーディングスタイルのチェックを行う。
- そのプルリクエストで触ったファイルだけをチェックする。
- 運用に慣れてもらうため、ひとまず簡単に直せるようなルールのみをerrorにする。
- 差分のみをfixできるshellを念の為作っておく。
- メンバーのエディタが多様なので、ESLintのチェックがエディタ上で表示されない場合があった。
- 編集したファイルを都度都度fixするという手間をなくし、fix忘れを防ぐため。
手順
1. コーディング規約を決める
コーディング規約がない場合、まずはチームでコーディング規約を決めることから始めます。
細かいところはまずはスタンダードに乗っかると楽なので、「みんなが常日頃気になっているところ」だけ話しておくのが良いと思います。
- インデント(ソフトインデント / ハードインデント)
- 改行コード(LF / CRLF)
- 括弧の位置 等々…
話し合いの段階でESLintの推奨設定やJavaScript Standard Styleを見ておくと、「推奨や標準はこうなんだ」と参考になります。
- ESLintの推奨設定:https://eslint.org/docs/rules/ (左にチェックマークが付いているものが推奨設定)
- JavaScript Standard Style:https://standardjs.com/rules.html
2. ESLintの導入
淡々と導入手順を記していきますが、よく分からなかったら公式サイトを参照してみてください。
npmが動く環境であることを前提とします。
package.json
がないプロジェクトなら、下記コマンドでpackage.json
を作ります。
$ npm init -y
ESLintをインストールします。
$ npm install --save-dev eslint
ESLintを簡単に実行できるように、スクリプトを定義しておきます。package.json
のscripts
に下記のようなscriptを定義します。
"scripts": {
"lint": "eslint",
"fix": "eslint --fix"
}
3. ESLintのルールを整備する
コーディングルールを設定していきます。
プロジェクトフォルダの直下に.eslintrc.json
というファイルを作ります。
{
"extends": "eslint:recommended"
}
"eslint:recommended"
はESLintの推奨設定に則ることを意味します。
ESLintのコーディングルールは恐ろしいほどたくさんあるので、推奨設定から調整していくのがおすすめです。
先ほどスクリプト定義したので、下記のようにコマンドを打つとESLintが動きます。
$ npm run lint [jsファイルのパス]
errorやwarnがたくさん出るかもしれませんが、jQueryのプロジェクトなら"env"
に"jquery"
を追加したり、"globals"
に変数を設定したり、みんなで決めたルールに沿って"rules"
を追加したりして調整していきます。
{
"env": {
"browser": true,
"jquery": true
},
"extends": "eslint:recommended",
"rules": {
"no-redeclare": "warn",
"no-unused-vars": "warn",
"camelcase": "warn",
"linebreak-style": ["error", "unix"],
"indent": ["error", "tab", { "SwitchCase": 1 }],
"eol-last": ["error", "always"],
"no-trailing-spaces": "error",
"no-multiple-empty-lines": ["error", { "max": 1 }],
"space-before-blocks": ["error", "always"],
"quotes": ["error", "single"],
"semi": ["error", "always"],
"comma-style": ["error", "last"],
"space-before-function-paren": ["error", "never"],
"func-call-spacing": ["error", "never"],
"block-spacing": ["error", "always"],
"array-bracket-spacing": ["error", "never"],
"no-array-constructor": "error",
"spaced-comment": ["error", "always"]
}
}
今回はESLintでfixできるようなものは基本的にerrorにし、簡単にfixできないものはwarnにしました。CircleCIが落ちる、直す、通る、という一連の流れをメンバーに体感してもらいたかったためです。
4. 差分ファイルだけlintとfixができるshellを書く
CircleCIで動かす用のshellと、ローカルで差分だけfixするようなshellを作ります。
- lint.sh
- masterとの差分があるjsファイルだけlintします。
- CircleCIに載せる用。ローカルでも動きます。
- lint-fix.sh
- masterとの差分があるjsファイルだけfixします。
- ローカルでESLintが直せるerrorを直します。
これらのファイルをプロジェクトディレクトリ直下に置いた前提で話を進めます。
#!/bin/bash
echo 'CIRCLE_BRANCH: ' ${CIRCLE_BRANCH}
TARGET_BRANCH=${CIRCLE_BRANCH}
# masterブランチへのmerge時はチェックしない
if [ "$TARGET_BRANCH" = 'master' ]; then
echo 'SKIP on merge into master'
exit 0
fi
# ローカルでの実行用にカレントブランチをセットする
if [ "$TARGET_BRANCH" = '' ]; then
TARGET_BRANCH=$(git rev-parse --abbrev-ref HEAD)
fi
echo 'TARGET_BRANCH: ' $TARGET_BRANCH
BASE_BRANCH=origin/master
echo 'BASE_BRANCH: ' $BASE_BRANCH
files=$(git diff --name-only $TARGET_BRANCH $BASE_BRANCH | grep -E '.js$')
error=false
for file in ${files}; do
npm run lint -s -- ${file}
result=$?
if [ $result -ne 0 ]; then
error=true
fi
done
if $error; then
exit 1
fi
exit 0
#!/bin/bash
# origin/masterをベースブランチにセット
BASE_BRANCH=origin/master
echo 'BASE_BRANCH: ' $BASE_BRANCH
files=$(git diff --name-only $BASE_BRANCH | grep -E '.js$')
error=false
for file in ${files}; do
npm run fix -s -- ${file}
result=$?
if [ $result -ne 0 ]; then
error=true
fi
done
if $error; then
exit 1
fi
exit 0
ファイルができたら、適当なjsファイルに差分を作って、下記のように実行して試してみます。
$ ./lint.sh
$ ./lint-fix.sh
5. CircleCIに導入
CircleCI側でリポジトリの追加ができている前提で、.circleci/config.yml
に下記を記述します。
version: 2
jobs:
build:
docker:
- image: circleci/node:10.16.0
steps:
- checkout
- run: npm install
- run: ./lint.sh
nodeが使えるimageを用意して、./lint.sh
しています。
ここでは当時最新のLTS(long term support)だったnode v10系を使っています。
これをプッシュすれば、CircleCIによるlintが走るはずです!
プルリクの最後の方にこんな感じで表示されると思います。
6. チームメンバーに説明・ドキュメント整備・各々の環境やエディタで使えるように設定
継続的に取り組むために1番大事なことです。
下記のようなことを伝えました。
- プルリクにこんなのが付くようになるよ
- エラーメッセージはこうやって見るよ
- CIが落ちたら直す。レビュワーはマージせずに一報入れる。
また、チームメンバー各々の環境やエディタで使えるように、nodeの環境構築やプラグインを入れる時間を取りました。
- Atom:AtomにESLint導入した
- VS Code:https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
最後に
今回の開発の部分は、今年7月に行われた開発合宿で行いました。足湯コーディングめっちゃ良かった〜〜〜!
足湯コーディングしたい方はJOIN US!!!
スペシャルサンクス
- 弊社の素敵文化・フロントエンド共有会で相談に乗ってくれた@AmatsukiKuさん
- 合宿で罵詈雑言と共にCircleCIのことを教えてくれた@inductor(呼び捨て)