Macの環境をdotfilesでセットアップしてみた

2022.03.11

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

(追記)本記事の内容を改良した最新版のdotfilesのブログ記事を公開しました!


こんにちは!仕事部屋に頻繁に犬が突撃してきて、集中力が切れて困っているつくぼし(tsukuboshi0755)です!

最近クラスメソッドに入社して、Macをセットアップする機会がありました。
その際に自分用のdotfilesを使ってセットアップをしてみたので、紹介させていただこうと思います!

dotfilesって何?

元々は、ホームディレクトリに存在するドット(.)から始まる設定ファイル(.bash_profileだったり.bashrcだったり)を管理するリポジトリという意味らしいです。
GitHubで公開する事もできるので、他の方のdotfilesも見る事もできたりします。

ただ色んなdotfilesを見てみると、ドットから始まるか始まらないかに関係なく、セットアップに必要な設定ファイルであればガンガン置いてる事が多いです笑

dotfilesレイアウトの紹介

ここからは、自分のMac用のdotfilesの構成について紹介していきたいと思います!
以下に私のdotfilesの中身について抜粋して、記載しておきます。

※一部簡略化しているため、実際の私のdotfilesとは異なる箇所があります。

dotfiles
├── .bin
│   ├── .Brewfile
│   ├── .bash_profile
│   ├── .bashrc
│   ├── .gitconfig
│   ├── .gitignore_global
│   ├── brew.sh
│   ├── defaults.sh
│   ├── init.sh
│   └── link.sh
├── .github
│   └── workflows
│       └── main.yml
├── Makefile
└── README.md

dotfilesの完全版は、以下のGitHubのURLに上げてます。

https://github.com/tsukuboshi/dotfiles

以上の内、Macのセットアップにおいて重要なファイルを解説してみたいと思います!

Makefileによる自動セットアップ

dotfilesでセットアップを行うには、GitHubからリポジトリをダウンロードした後に、様々なセットアップ用コマンドを実施する必要があります。
毎回手動でコマンドを叩くのは面倒なので、何らかの手段でセットアップを自動化するのがオススメです。

自分の場合はMakefileを用いて、makeコマンドを叩くだけで対象のシェルスクリプトが全て実行されるように設定してます!

Makefile

# Do everything.
all: init link defaults brew

# Set initial preference.
init:
	.bin/init.sh

# Link dotfiles.
link:
	.bin/link.sh

# Set macOS system preferences.
defaults:
	.bin/defaults.sh

# Install macOS applications.
brew:
	.bin/brew.sh

自動セットアップのツールとしてはAnsibleが有名ですが、Macの場合Ansibleのインストールを一度挟まなければいけないのが欠点です。

対してMakefileであれば、ファイルさえ配置してしまえばMacに何もインストールせずともmakeコマンドが使えるため、個人的にはこっちの方が好きですね〜

Macの初期セットアップ

init.shには、Macで一番最初に実行するべきコマンドを記載しています。
このスクリプトを実施する事で、zsh→bashへの切り替えと、xcode及びbrewコマンドのインストールができます。

init.sh

#!/bin/bash

if [ "$(uname)" != "Darwin" ] ; then
	echo "Not macOS!"
	exit 1
fi

# Set bash
chsh -s /bin/bash

# Install xcode
xcode-select --install > /dev/null

# Install brew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" > /dev/null

個人的にbashが好きなのであえて切り替えてますが、さすがにそろそろzshに移行しないとですね...

設定ファイルのシンボリックリンク作成

link.shには、ホームディレクトリに設定ファイルのシンボリックリンクを作成するコマンドを記載しています。
このスクリプトを実施する事で、ドットから始まるオブジェクトの内、シンボリックリンクを貼る必要がないものは予め除いた上で、それ以外のファイルのシンボリックリンクをホームディレクトリに作成します。

link.sh

#!/bin/bash

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

for dotfile in "${SCRIPT_DIR}"/.??* ; do
    [[ "$dotfile" == "${SCRIPT_DIR}/.git" ]] && continue
    [[ "$dotfile" == "${SCRIPT_DIR}/.github" ]] && continue
    [[ "$dotfile" == "${SCRIPT_DIR}/.DS_Store" ]] && continue

    ln -fnsv "$dotfile" "$HOME"
done

.gitconfig.gitignore_globalといったgitの設定ファイルの他に、bash用に.bash_profile.bashrcのシンボリックリンクを貼っています!

追加コマンド/アプリのインストール

brew.shには、Macに追加で必要なコマンドツールやデスクトップアプリをインストールするHomebrewコマンドを記載しています。
Macに追加で必要なコマンドやアプリを.Brewfileに予め記載した上で、このスクリプトを実行すると、brew bundle —-globalコマンドにより.Brewfileが読み込まれ、一括インストールを実施する事ができます。 (めちゃくちゃ便利!)

brew.sh

#!/bin/bash

if [ "$(uname)" != "Darwin" ] ; then
	echo "Not macOS!"
	exit 1
fi

brew bundle --global

.Brewfile

cask_args appdir: "/Applications"

tap "heroku/brew"
tap "homebrew/bundle"
tap "homebrew/cask"
tap "homebrew/cask-versions"
tap "homebrew/core"

brew "anyenv"
brew "bash-completion"
brew "exa"
brew "git"
brew "git-secrets"
brew "heroku"
brew "jq"
brew "mas"
brew "rsync"
brew "tree"
brew "watch"
brew "wget"

cask "alfred"
cask "appcleaner"
cask "cheatsheet"
cask "docker"
cask "firefox"
cask "iterm2"
cask "keyboardcleantool"
cask "notion"
cask "rectangle"
cask "skitch"
cask "sourcetree"
cask "the-unarchiver"
cask "visual-studio-code"

.Brewfileでは、原則コマンドツールはbrew、デスクトップアプリはcaskで記載する事で、それぞれインストールする事ができますよ〜

Macの環境設定

defaults.shには、Mac自体の環境設定を操作するdefaultsコマンドを記載しています。
このスクリプトでは、defaultsコマンドで環境設定を実施した後、環境設定をいじったコンポーネントを一度落とす事で、設定を反映してます!

defaults.sh

#!/bin/bash

if [ "$(uname)" != "Darwin" ] ; then
	echo "Not macOS!"
	exit 1
fi

# ====================
#
# Base
#
# ====================

# Disable auto-capitalization
defaults write NSGlobalDomain NSAutomaticCapitalizationEnabled -bool false

# ====================
#
# Dock
#
# ====================

# Disable animation at application launch
defaults write com.apple.dock launchanim -bool false

# ====================
#
# Finder
#
# ====================

# Disable animation
defaults write com.apple.finder DisableAllAnimations -bool true

# Show hidden files by default
defaults write com.apple.finder AppleShowAllFiles -bool true

# Show files with all extensions
defaults write NSGlobalDomain AppleShowAllExtensions -bool true

# Display the status bar
defaults write com.apple.finder ShowStatusBar -bool true

# Display the path bar
defaults write com.apple.finder ShowPathbar -bool true

# ====================
#
# SystemUIServer
#
# ====================

# Display date, day, and time in the menu bar
defaults write com.apple.menuextra.clock DateFormat -string 'EEE d MMM HH:mm'

# Display battery level in the menu bar
defaults write com.apple.menuextra.battery ShowPercent -string "YES"

for app in "Dock" \
	"Finder" \
	"SystemUIServer"; do
	killall "${app}" &> /dev/null
done

defaultsコマンドで可能な環境設定は非常に多岐に渡るので、個人的にはまだまだ増やしていきたい所ですね〜

自動セットアップのCI/CD

せっかくGitHubにコードを上げているので、GitHub Actionsを用いたCI/CDをmain.ymlに組み込んでいます!

main.yml

# This is a basic workflow to help you get started with Actions

name: Dotfiles CI

# Controls when the action will run.
on:
  # Triggers the workflow on push or pull request events but only for the main branch
  push:
    branches: [ main ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: macos-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      # Runs a single command using the runners shell
      - name: Set MacOS.
        run: make

今回の場合だと、テストもmakeコマンドのみで完結するのが割と好きです笑

最後に

dotfilesは、普段からMacやLinuxを触っているエンジニアであれば、結構イメージしやすいと思います。
またシェルスクリプトを自分で考えて作る必要が生じるので、シェルによる自動化の勉強にもつながります!
何より作ってて楽しいです!!笑

もし興味のある方は、GitHubに様々なdotfilesがたくさん上がっているので、ぜひ参考にしながら作成してみると良いですよ笑
以上、dotfilesの面白さを広めたいつくぼしでした!