ハマったのでメモ。
大前提として、 WSL と Docker for Windows をうまく連携しておく必要がある。
以下のような手順。
ただし、
についてはもっと楽な解決法がある。 WSL 上に /etc/wsl.conf
というファイルをおけば WSL 側のマウントポイントを変えられるので、これを Docker for Windows に合わせてしまえば良い。
Automatically Configuring WSL – Windows Command Line Tools For Developers
$ cat /etc/wsl.conf [automount] root = / options = "metadata"
これで circleci local execute
も実行できる準備は整っているのだけど、一点だけ問題が。デフォルトの状態だと、 symlink が読めず、以下のようなエラーが出る。以下は、 pipenv
を .venv
で運用しているプロジェクトでのエラー例。
mkdir -p /home/circleci/project && cp -r /tmp/_circleci_local_build_repo/. /home/circleci/project cp: cannot read symbolic link '/tmp/_circleci_local_build_repo/./.venv/bin/python': No such file or directory
この解決策は以下に書かれている。
Yes, enabling developer mode fixes the symlink problem.
Developer mode は、Settings > Update & Security > For developers > Use developer features と進むとある。一つ重要な注意は、 Developer mode が有効となってから実行された ln -s
だけが Docker for Windows より読めるという点である。よって、 Developer mode はプロジェクトを始める前に有効にしておく必要がある。もしくは、問題となっている symlink をすべて削除して、作成し直す必要がある(というスクリプトを書いたほうが早そうだなあと思った)。
しかし、 pipenv
と .venv
で使っている場合について言えばこれでもうまくいかない。 WSL のローカルである /home/some-user/.pyenv
などへの symlink があり、これは Docker for windows からは見えないからだ。 symlink については、 env VIRTUALENV_ALWAYS_COPY=1 pipenv install
という実行の仕方で .venv
を作ればできなくなる。これで、 Checkout code フェーズでのエラーは抑えられた。
しかし、まだ終わらない。そもそもの問題として、 .pyenv
以下にインストールされているツールチェーンは、 #!/home/some-user/.pyenv/versions/3.7.2/bin/python3.7
などのシェバングを持っている。 .venv
はこれらをコピーしただけなので、当然同じシェバングを持つ。こんなものをコンテナ内に持っていっても、実行できるわけがない(試してないけど、この辺は Windows 以外でも起きる問題のはず)。
.venv
を複数の環境で使い回すというのがそもそも間違えていると考えられる。よって、 circleci local execute
する場合には .venv
を消してしまったほうがいいだろう。 .cricleci/config.yml
で、ローカル実行のときだけ .venv
を消すようにする。
- run: name: Remove .venv for local execute command: | if [[ $CIRCLE_SHELL_ENV =~ "localbuild" ]]; then rm -rf /home/circleci/project/.venv fi
ここまでやって、ようやく circleci local execute
できるようになった。なんとも辛い。
そもそもコンテナ内では PIPENV_VENV_IN_PROJECT
は指定しないほうがいい気はするのだが、 circleci のキャッシュを使うためには利用するディレクトリを固定したく、そのために指定している。