LCL Engineers' Blog

バス比較なび・格安移動・バスとりっぷを運営する LCLの開発者ブログです。

ジョインメンバーのためにmacOSの初回セットアップをチョットダケ自動化するTips

モバイルエンジニアの山下です。

LCLでは開発端末としてエンジニアメンバー全員にMacを支給しており、新しくメンバーがジョインした際もMBP or iMacを購入しています。
その際、ジョインメンバーには初日にmacOSの初回セットアップをしてもらう必要があるのですが、手動でのセットアップでは以下の問題が度々発生しました。

  • セットアップ項目を思い出す必要がある
  • セットアップ項目がメンバーによってバラバラ
  • インストールの手順が面倒で時間が掛かる
  • インストール漏れがあったりする
  • 面倒くさい

その他にも既存メンバーによる最低限必要なツール類の洗い出しと共有が発生するなど、このままでは、毎回手間と時間が掛かってしまうためインストール周りを自動化することにしました。

※開発環境は自由なので、自身でdotfilesなどを用意しているメンバーはこちらを使う必要はありません

実装方法

今回使うパッケージ管理ツールは以下となります。
※ 本記事ではパッケージ管理ツールやその他インストール対象の説明は省きます。

今回はsetup.shという名前のシェルを作りました。インストール対象は分野によって異なるため、引数で判断するようにしました。

# !/bin/sh

if [ $# -ne 1 ]; then
cat <<__EOT__
引数にプロダクトのプラットフォームを指定してください.
 all
 web
__EOT__
exit 0;
fi

case $1 in
  "all" ) ;;
  "web" ) ;;
      * ) echo "Usage: sh setup.sh [all|web]" 1>&2
          exit 1 ;;
esac

echo $1;

これで$ sh setup.sh all(or web)とすれば、$1に引数の値が保持されます。

次にHomebrewをインストールします。

if ! type brew > /dev/null 2>&1; then
  ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
fi

Homebrewをインストールできたので、これを使ってツールをインストールします。
インストール対象は下記で言うbrew_$1.txtに書かれています。つまり、allを引数に保たせた場合はbrew_all.txtを読み込みます。

brew_all.txtの一部

git
git-flow
hub
mas
node

それぞれのテキストデータでツール名を羅列しているため、ループで回してインストールコマンドを実行しています。

for app in `cat brew_$1.txt`; do
  if ! type ${app} > /dev/null 2>&1; then
    brew install ${app}
  else
    echo "Installed ${app}"
  fi
done

以下、同じ要領でcaskとmasから各アプリケーションをインストールしています。

(続き)

if [ -n "`$SHELL -c 'echo $ZSH_VERSION'`" ] && ! grep -E -q 'HOMEBREW_CASK_OPTS' ~/.zshrc; then
  echo 'export HOMEBREW_CASK_OPTS="--appdir=/Applications"' >> ~/.zshrc
  source ~/.zshrc
elif [ -n "`$SHELL -c 'echo $BASH_VERSION'`" ] && ! grep -E -q 'HOMEBREW_CASK_OPTS' ~/.bashrc; then
  echo 'export HOMEBREW_CASK_OPTS="--appdir=/Applications"' >> ~/.bashrc
  source ~/.bashrc
fi

missing_formulae=()
desired_formulae=(`cat cask_$1.txt`)
# cask
installed=`brew cask list`

for index in ${!desired_formulae[*]}
do
  formula=`echo ${desired_formulae[$index]} | cut -d' ' -f 1`
  if [[ -z `echo "${installed}" | grep "^${formula}$"` ]]; then
    missing_formulae=("${missing_formulae[@]}" "${desired_formulae[$index]}")
  else
    echo "Installed ${formula}"
  fi
done

if [[ "$missing_formulae" ]]; then
  list_formulae=$( printf "%s " "${missing_formulae[@]}" )

  echo "Installing missing Homebrew formulae..."
  brew cask install $list_formulae

  [[ $? ]] && echo "$(tput setaf 2)Installed missing formulae ✔︎$(tput sgr0)"
fi

echo "Cleanup Homebrew..."
brew cleanup
echo "$(tput setaf 2)Cleanup Homebrew complete. ✔︎$(tput sgr0)"

for app in `sed '/^#/d' mas_$1.txt`; do
  if ! type ${app} > /dev/null 2>&1; then
    mas install ${app}
  else
    echo "Installed ${app}"
  fi
done

cask_all.txtの一部

google-chrome
google-drive-file-stream
google-japanese-ime
fork
docker
iterm2

『setup』リポジトリを作成してこれらのファイルをGitHub上で管理するようにしました。
最初にこのリポジトリをクローンしてシェルを叩くだけで各種インストールが終わります。

その他

ジョイン時に必要な情報を『setup』リポジトリと一緒に管理しています。

ブックマーク

以下のブックマークをフォルダ毎にまとめて、HTML形式でエクスポートして管理しています。

  • 社内イントラ
  • 利用しているサービス
  • 本番環境
  • ステージング環境など

各ドキュメント

LCLでは、働き方からサービスの仕様まで全てドキュメント化して誰でも閲覧できるようにしています。
入社後に最初に読むドキュメントも用意しているのですが、この記事の共有するために部長やメンバーが都度検索していました。

また、数日経つと本格的に仕様のドキュメントを探す必要があり、その都度に共有する動作が発生していました。
そのため、最初の方に読むドキュメントをREADME.mdにまとめて情報の起点になるようにしました。

f:id:lcl-engineer:20180731125737p:plain

最後に

これにより、初回セットアップの手間とそれに掛かる時間が格段に減りました。
各内容が可視化されたため、既存メンバーが別の分野に挑戦する際も同じ環境を作れるようになりました。

自動化とは関係ないですが、ドキュメントを探す手間がなくなったのもよかったです。
macOSのシステム環境設定など、セットアップは自動化できないものはドキュメントで残すようにしました。

シェルをついては、理解が浅いため難しいことはしていません。 もっと賢い書き方はいくらでもあるかもしれませんが、現状では問題なく動いているので少しずつ改善していきたいです。