〇〇env系ツールをanyenvで一括管理する

# はじめに
この記事は [フューチャーAdvent Calendar 2020](https://qiita.com/advent-calendar/2020/future) の20日目の記事です。

環境構築に便利な〇〇env系ツールを、もっと便利に扱える `anyenv` に感動したので、ブログ化しました。

## 開発言語のバージョン管理
複数プロジェクトに関わる場合、開発言語のバージョン管理は必須スキルです。
他の開発メンバーと利用バージョンを一致させなければ、フォーマッタ適用 → PRでの差分爆発が生じてレビュアーに袋叩きにされます。

なので、各エンジニアはそれぞれの創意工夫により、開発言語のバージョン管理問題を解決しています。

私の場合、環境構築ポリシーとして
- ローカル環境への直ダウンロードは厳禁
- 環境構築は基本的にDockerを使う

という方針を、ずっと貫いています。

...

スミマセン。強がりです。
貫けていませんでした。

### 〇〇env の多用
コロナ影響で在宅勤務へ移行した結果、NWの問題によりDockerがうまく使えない状況が増え、仕方なく〇〇env系ツールの利用を開始しました。

インストールした〇〇env系ツールは
- PJ開発はメインでgoを使う → goenv
- 環境Aはpythonのみ動く → pyenv
- 環境Bはrubyのみ動く → rbenv
- AWSのMFA(多要素認証)でet-otpを使う → jenv

というもので、開発作業で新しい言語が必要になるたびに、対応するツール1つ1つ追加していました。

これらは同じコマンド操作で設定可能なため、ストレスになるのはパッケージのダウンロード時間くらいだと思っていましたが、知らぬ間に開発環境汚染が進んでいました。

### bash_profileが汚れていた

担当業務で Vue.js のコードに触れる機会があり、新たに `nodenv` をインストールしようとしたところ
- 〇〇env系ツールの環境構築って、いっつも同じような環境変数を追加しているな
- bash_profileのメンテしてたっけ？

ということに気づき、cat ~/.bash_profile すると、↓こんな感じになっていました

```bash
...
# goenv
export GOENV_ROOT=$HOME/.goenv
export PATH=$GOENV_ROOT/bin:$PATH
eval "$(goenv init -)"

# pyenv
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

# jenv
export JENV_ROOT=$HOME/.jenv
export PATH="$HOME/.jenv/bin:$PATH"
eval "$(jenv init -)"

(rbenv, nodenv などの設定が続く...)
...
```

あれ？

開発環境が汚れないよう注意していたはずなのに
所々で微妙な違いがあり、綺麗な状態とは言い難い...

〇〇env系ツールが増えるごとに
bash_profileに追記し続けるのを止めたい

...

[anyenv](https://github.com/anyenv/anyenv) が便利そう！

## anyenvを使って綺麗にする
anyenv自体の説明前に、このツールを使うと何が綺麗になるか？から説明します。

すでにインストール済みのgoenv, pyenvなどはanyenv経由での再設定が必要になりますが、それを乗り越えれば、bash_profile に必要な `〇〇env系ツールの記述` は、以下のみで十分となります。将来的に新しい 〇〇env が必要になった場合でも、bash_profile への追記は不要です。

```bash
...
# anyenv
eval "$(anyenv init -)"
...
```

goenv, jenvごとにPATHを設定 & initする煩わしい記述から解放され、かつ、操作方法は従来の〇〇env系コマンドを利用可能なので、開発環境汚染を少しでも減らしたいエンジニアであれば、このツールを使わない理由は無いと思います。

## anyenvとは？
> anyenv - All in one for **env

> This is a simple wrapper for rbenv style environment managers. You don't have to git clone or modify your shell profile for each **env anymore if you install anyenv.

https://github.com/anyenv/anyenv#anyenv---all-in-one-for-env

端的に言うと、**複数の〇〇envを一括管理**できる便利ツールです。

執筆時点(2020.12.10)では、以下〇〇envパッケージがanyenvでは利用可能です。
有名どころは網羅しているので、多くの開発プロジェクトで導入可能だと思います。

```bash
$ anyenv install -l
  Renv       #R
  crenv      #Crystal
  denv       #D
  erlenv     #Erlang
  exenv      #Elixir
  goenv      #Go
  hsenv      #Haskell
  jenv       #Java
  jlenv      #Julia
  luaenv     #Lua
  nodenv     #Node.js
  phpenv     #PHP
  plenv      #Perl
  pyenv      #Python
  rbenv      #Ruby
  sbtenv     #Sbt
  scalaenv   #Scala
  swiftenv   #Swift
  tfenv      #terraform
```

上記から欲しい言語をインストールすれば、あとはいつも通りの〇〇env操作コマンドで環境構築可能です。

## anyenvのインストール手順
### macの場合
Homebrewを利用します。

```bash
$ brew install anyenv
$ echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l

$ anyenv install --init # enter "y"
```

### Linux環境の場合
GitHubから直接引っ張ってきます。

```bash
$ git clone https://github.com/anyenv/anyenv ~/.anyenv
$ echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l

$ anyenv install --init # enter "y"
```

最後に `$ anyenv install 〇〇env` で欲しいパッケージを取得すれば、これまで通りの〇〇envコマンドが利用できます。

### ex) node.jsのv15.0.1が欲しい場合
anyenvを利用し、nodenvを取得します。

```bash
$ anyenv install nodenv
$ exec $SHELL -l

$ anyenv versions
nodenv:
Warning: no Node detected on the system
```

次は、nodenvでv15.0.1を取得します。

```bash
$ nodenv install 15.0.1
$ nodenv global(local) 15.0.1

$ node -v
v15.0.1
```

以上により、Node.js:v15.0.1 が利用可能となりました。


私の開発では goenv, pyenv, jenv, nodenv が必須なので、以下の設定を入れています。
`$ anyenv versions` により、各envの設定状況が一覧できます。

```bash
$ anyenv versions
goenv:
  system
  1.XX.0
* 1.YY.0 (set by /Users/<username>/.anyenv/envs/goenv/version)
jenv:
  system
* XX.0 (set by /Users/<username>/.anyenv/envs/jenv/version)
nodenv:
  system
* XX.0 (set by /Users/<username>/.anyenv/envs/nodenv/version)
pyenv:
  system
  XX.0
* YY.0 (set by /Users/<username>/.anyenv/envs/pyenv/version)
```

anyenvインストール以前に設定したgoenvやpyenvの環境変数が残っている場合は、bash_profileから削除することも忘れないようご注意ください。

# まとめ
- 環境変数、`echo 'export hogehoge"' >> ~/.bash_profile`で追加したまま放置していませんか
- 複数の〇〇env系ツールを使っているなら、anyenvの利用がオススメ
- anyenvでbash_profileがスッキリ