Homebrewのbrew bundleを利用したパッケージ管理

# はじめに

自身のメモとして、本記事ではmacOS上でパッケージ管理するシステムのひとつであるHomebrewの`brew bundle`の使い方について記述します．`brew bundle`を利用することでHomebrewでパッケージ及びGUIのアプリの一括管理を行うことが出来ます．

# Homebrewとは

Homebrew（ほーむぶるー）とは、macOS上で動作するパッケージ管理システムです．[パッケージ管理システム](https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E7%AE%A1%E7%90%86%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0#:~:text=%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E7%AE%A1%E7%90%86%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%EF%BC%88%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%8B%E3%82%93,%E7%AE%A1%E7%90%86%E3%81%99%E3%82%8B%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82)とはパッケージをインストールしたりアンインストールしたい出来るシステムのことを指します．Homebrewを利用することで、Macのターミナルから簡単にパッケージの追加・削除を行うことが出来ます．

# 動作環境の確認

今回動作確認するHomebrewのバージョンを確認します．

```bash
$ brew -v
Homebrew 3.1.12
Homebrew/homebrew-core (git revision a82b26bb6f; last commit 2021-06-15)
Homebrew/homebrew-cask (git revision 71d323d9f3; last commit 2021-06-14)
```

# `brew bundle`の概要

Homebrewではターミナル上で動作するパッケージとGUIアプリ管理ができます．brewのコマンドを都度実行し、パッケージの追加削除を行っても良いのですが、`brew bundle`を利用することで一括で追加・削除ができ、とても便利です．`brew bundle`は設定ファイルのBrewfileを読み込みむことで、パッケージを自動的に追加・削除してくれます．

`brew bundle`を使うメリットしては、新たにPCのセットアップするする際に、Brewfileさえあれば必要なパッケージを一括インストールができ、設定の手間が省けます．

下記がBrewfileの一例です．以降で、下記の内容を噛み砕いて説明していきます．

```bash
cask_args appdir: "/Applications"

brew 'anyenv'
brew 'ctop'
brew 'curl'
brew 'jq'
brew 'htop'
brew 'mackup'
brew 'mas'
brew 'peco'
brew 'tree'
brew 'zsh'

cask "1password"
cask "aws-vpn-client"
cask "discord"
cask "docker"
cask "google-backup-and-sync"
cask "google-chrome"
cask "google-japanese-ime"
cask "iterm2"
cask "kindle"
cask "microsoft-auto-update"
cask "microsoft-office"
cask "miro"
cask "notion"
cask "parallels"
cask "visual-studio-code"
cask "webex-meetings"

mas "Keynote", id: 409183694
mas "Slack", id: 803453959
mas "ScreenFlow9", id: 1475796517
mas "TweetDeck", id: 485812721

# cask "sourcetree"
```

# `brew`でのパッケージ管理

ターミナル上で動作するパッケージの記述は下記になります．インストールしたパッケージを記載します．

```bash
brew 'anyenv'
brew 'ctop'
brew 'curl'
brew 'jq'
brew 'htop'
brew 'mackup'
brew 'mas'
brew 'peco'
brew 'tree'
brew 'zsh'
```

# `mas`でのパッケージ管理

Mac App Storeからインストールするアプリケーションは`mas`を利用してインストールします．下記では、Mac App StoreからKeynote、Slack、TweetDeck、そして有料のScreenFlow9をインストールします．

```bash
mas "Keynote", id: 409183694
mas "Slack", id: 803453959
mas "ScreenFlow9", id: 1475796517
mas "TweetDeck", id: 485812721
```

下記がフォーマットになります．

```bash
mas "<application_name>", id: <application_id>
```

Mac Apple Storeからアプリケーションをインストールする場合は、アプリケーション名とアプリケーションのIDが必要です．これらを取得するために、まずGoogle検索を行います．App Storeの検索結果をクリックします．

![_2021-06-15_12.55.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/920063/6fdd0f22-a736-f160-c48b-b785dead6cf6.png)

「Keynote」のApp StoreのURLにアプリケーションIDは埋め込まれています．Keynoteの場合は、アプリケーション名は「Keynote」、アプリケーションIDは「361285480」となります．なお、アプリケーションを一意に特定するのはアプリケーションIDのため、厳密にはアプリケーション名は任意の文字列を指定出来ます．

```bash
https://apps.apple.com/jp/app/keynote/id361285480
```

![_2021-06-15_12.55.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/920063/66e7a381-0917-53fa-fc7a-38a6d4abec0b.png)


よって、Keynoteを`brew bundle`でインストールするのに必要な１行は下記になります．

```bash
mas "Keynote", id: 409183694
```

masを利用する際の注意点としてMac App Store一度登録しているアプリケーションが対象となるため、新規にアプリケーションをインストールする場合は、一度Mac App Storeで手動で購入してからアプリケーションを削除し`brew bundle`で登録すると良いです．

# `cask`でのパッケージ管理

Mac App Storeを介さないアプリケーションは`cask`を利用してインストールします．下記が例になります．

```bash
cask_args appdir: "/Applications"

cask "1password"
cask "aws-vpn-client"
cask "discord"
cask "docker"
cask "google-backup-and-sync"
cask "google-chrome"
cask "google-japanese-ime"
cask "iterm2"
cask "kindle"
cask "microsoft-auto-update"
cask "microsoft-office"
cask "miro"
cask "notion"
cask "parallels"
cask "visual-studio-code"
cask "webex-meetings"
```

下記がフォーマットとなります．

```bash
cask "<application_name>"
```

`cask`でアプリをインストールするには、`<application_name>`を特定する必要がります．[Homebrew Fomulaeのサイト](https://formulae.brew.sh/)からアプリケーション名を検索することが出来ます．検索ボックスに対象となるアプリケーション名を記入し検索します．今回は1Passwordのアプリケーションを検索します．
![_2021-06-15_15.43.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/920063/8118ff73-a5c3-19c1-eace-b0a20e414e54.png)

検索結果が下記になります．アプリケーション名は`1password`になります．
![_2021-06-15_15.43.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/920063/c81d2da5-67be-bce1-5b02-05086bf64431.png)


よって、1Passwordを`brew bundle`でインストールするのに必要な１行は下記になります．

```bash
cask "1password"
```

# brew bundleでパッケージを一括管理

`brew bundle`の実行してパッケージの追加・更新・削除を行います．処理が完了するまで数分時間がかかります．

ここでは、参考までに 「sourcetree」を新規に追加して`brew bundle`を実行します．「sourcetree」が追加されていれば成功です．

Brewfileに`cask "sourcetree"`を追加

```bash
cask_args appdir: "/Applications"

brew 'anyenv'
brew 'ctop'
brew 'curl'
brew 'jq'
brew 'htop'
brew 'mackup'
brew 'mas'
brew 'peco'
brew 'tree'
brew 'zsh'

cask "1password"
cask "aws-vpn-client"
cask "discord"
cask "docker"
cask "google-backup-and-sync"
cask "google-chrome"
cask "google-japanese-ime"
cask "iterm2"
cask "kindle"
cask "microsoft-auto-update"
cask "microsoft-office"
cask "miro"
cask "notion"
cask "parallels"
cask "visual-studio-code"
cask "webex-meetings"

mas "Keynote", id: 409183694
mas "Slack", id: 803453959
mas "ScreenFlow9", id: 1475796517
mas "TweetDeck", id: 485812721

cask "sourcetree"
```

`brew bundle`で追加

```bash
$ brew bundle

Using anyenv
Using ctop
Using curl
Using jq
Using htop
Using mackup
Using mas
Using peco
Using tree
Using zsh
Using 1password
Using aws-vpn-client
Using discord
Using docker
Using google-backup-and-sync
Using google-chrome
Using google-japanese-ime
Using iterm2
Using kindle
Using microsoft-auto-update
Using microsoft-office
Using miro
Using notion
Using parallels
Using visual-studio-code
Using webex-meetings
Using Keynote
Using Slack
Using ScreenFlow9
Using TweetDeck
Installing sourcetree
Homebrew Bundle complete! 31 Brewfile dependencies now installed.
```

sourcetreeが追加された
![_2021-06-15_22.40.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/920063/c9d20696-8c4c-674a-48b1-0662709b72f3.png)

今度はsourcetreeをアンインストールする．Brewfileからコメントアウト

```bash
cask_args appdir: "/Applications"

brew 'anyenv'
brew 'ctop'
brew 'curl'
brew 'jq'
brew 'htop'
brew 'mackup'
brew 'mas'
brew 'peco'
brew 'tree'
brew 'zsh'

cask "1password"
cask "aws-vpn-client"
cask "discord"
cask "docker"
cask "google-backup-and-sync"
cask "google-chrome"
cask "google-japanese-ime"
cask "iterm2"
cask "kindle"
cask "microsoft-auto-update"
cask "microsoft-office"
cask "miro"
cask "notion"
cask "parallels"
cask "visual-studio-code"
cask "webex-meetings"

mas "Keynote", id: 409183694
mas "Slack", id: 803453959
mas "ScreenFlow9", id: 1475796517
mas "TweetDeck", id: 485812721

# cask "sourcetree"
```

`brew bundle cleanup`でBrewfileに存在しないパッケージを削除．

```bash
$ brew bundle cleanup

Would uninstall casks:
sourcetree
Would uninstall formulae:
libmetalink                                                                                        pcre2
Would untap:
homebrew/cask
```

理由はわからないが削除されない場合は、`brew uninstall`で削除

```bash
$ brew uninstall sourcetree
```

# Dropboxにて設定ファイルを保存

筆者の環境では、BrewfileはDropboxに置いています．何かあっても、Dropboxに常時設定ファイルが保存されているので安心です．

```bash
$ cd ~/Dropbox
$ ls Brewfile
```

# 参考

- [https://brew.sh/index_ja](https://brew.sh/index_ja)
- [https://qiita.com/zaburo/items/29fe23c1ceb6056109fd](https://qiita.com/zaburo/items/29fe23c1ceb6056109fd)
- [https://original-game.com/homebrew/](https://original-game.com/homebrew/)
- [https://ja.wikipedia.org/wiki/Homebrew_(パッケージ管理システム)](https://ja.wikipedia.org/wiki/Homebrew_(%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E7%AE%A1%E7%90%86%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0))
- [http://bcl.sci.yamaguchi-u.ac.jp/~jun/notebook/mac/brew/](http://bcl.sci.yamaguchi-u.ac.jp/~jun/notebook/mac/brew/)
- [https://forest.watch.impress.co.jp/docs/news/1305182.html](https://forest.watch.impress.co.jp/docs/news/1305182.html)
- [https://forest.watch.impress.co.jp/docs/news/1292914.html](https://forest.watch.impress.co.jp/docs/news/1292914.html)
- [https://fukatsu.tech/homebrew](https://fukatsu.tech/homebrew)
- [https://qiita.com/vochicong/items/f20afc89a6847cd58f0f](https://qiita.com/vochicong/items/f20afc89a6847cd58f0f)