« ^ »

Evolution GymのCIが失敗している問題を直す

所要時間: 約 8分

TL;DR

Evolution Gymのリリース作業を以前担当させていただいた。その時には特に問題なくGithub Acitions上のUbuntuでテストが実行できる状態になっていた。あの頃はまだ肌寒い初春だった。あれから数ヶ月経ち、春が過ぎ、夏が過ぎ、秋になって、そしてCIが失敗するようになっていた。その間1コミットも入っていない。半年前には出来ていたのに、何もしてないのに壊れた。インターネットというものは総じてそういうものなのだろう。コードベースに変更はない訳だから、OSやパッケージに何かしらあの頃とは差があるのだと思い、過去のGithub Actionsのログを見ようとしたが、ログの保持期間を過ぎており、過去にCIをパスしていたという事実しか分からなかった。新しくブランチを作成し幾つかの修正を入れ、Github Actionsを実行してみたが、その場しのぎの調査では全く理由が掴めなかった。過去にCIをパスしていたというのは、僕の夢か勘違いだったのかもしれないと思うけれど、Github Actionsの実行結果を見るとやっぱりパスしている。もういっその事CIをパスしていた事が夢であったら、新しい気持ちでこの問題に取り組めるような気もするけれど、どうしても気が乗らず1ヶ月ほどこの問題を放置していた。

正直誰かが良い方法を思い付いて修正する事を心のどこかで期待していた。しかし、実際にはそうはならなかった。以前に作られていたプルリクエストもあったが、そちらはそちらで、幾つかの問題があった。その問題は、マージした後に修正していってもよさそうなものではあったが、手放しでマージするという事にはならなかった。実際にはこの調査にも1週間ぐらい使った。

書籍の出版時期が迫り、もう後がなくなってきた。どうやら他力本願は叶わないらしい。仕方がないのでこの問題に取り組む事にした。その場しのぎ的なアプローチをして、以前打ちのめされたから、今回は足元からしっかり取り組む事にした。

以前のその場しのぎ的なアプローチというのは、適当にインストールするパッケージのバージョンを変更するなどして、Github Actions上で確認するという方針だった。Github Actions上の環境にはubuntu-22.04を使用していたが、全く綺麗なものという訳ではなさそうだった。環境を作成するためのGithub Actionsのプラグインを使っていたし、細かく各バージョンを確認もしていなかった。

今回はそういうやり方はせず、綺麗なubuntuの状態から必要なパッケージを手動でインストールし、ビルド及びテストができる事を確認する事にした。

ubuntu:22.04はDockerコンテナとして起動し、手動で環境を整えていく。まずubuntu:22.04にPython3.8を入れた。Python3.8の環境を作成するために以下のdebパッケージをインストールした。Python3.8はDeadsnakeからインストールする事にした。DeadsnakeはPPAにホスティングされているため、PPAの公開鍵をダウンロードするためにcurlも必要になった1

  • curl
  • python3.8 (from deadsnake)
  • python3.8-dev (from deadsnake)
  • python3.8-distutils (from deadsnake)
  • python3.8-venv (from deadsnake)

Python3を実行できる環境ができた。次にevogymをビルドして、失敗のログを確認しながらパッケージを足していった。必要なパッケージはREADMEに記載のあるものと、READMEに記載のないものがある。

READMEに記載のあるもの

  • xorg-dev
  • libglu1-mesa-dev

READMEに記載のないもの

  • cmake
  • gcc+
  • g++
  • git

ここまで環境を整備しても python3.8 setup.py build は失敗する。理由はGLEWを見つけられないという問題だ。これはcmakeが保持するFindGLEW.cmakeというスクリプトの問題で、GLEWが独自のパスにインストールされている時に、このライブラリを見つけられないというものだ。この問題は、環境変数を設定するだけでは解消できないようだったため、FindGLEW.cmakeというスクリプトをevogym自体に持たせ、そちらを参照させる事で回避した。これは半年前ぐらいに行った調査と対応だった。しかし理由はわからいが、今はそれが有効ではないようだ。

cmakeの設定ファイルで問題となっている事は分かっているから、その問題の箇所を削除した。

diff --git a/evogym/simulator/CMakeLists.txt b/evogym/simulator/CMakeLists.txt
index 09b6add..91462ce 100644
--- a/evogym/simulator/CMakeLists.txt
+++ b/evogym/simulator/CMakeLists.txt
@@ -19,7 +19,7 @@ endif()

 if(UNIX)
   find_package(OpenGL REQUIRED)
-  find_package(GLEW REQUIRED)
 endif()

 set(EXTERNAL_ROOT ${PROJECT_SOURCE_DIR}/externals)

そして再度evogymをビルドすると、ビルドできた。これを考えると、環境変数の設定すら必要ないという事が分かる。では find_package(GLEW REQUIRED) は本当に必要なのだろうか。ここが分からない所だ。git submoduleになっているため、不要なのではと思う。少なくともubuntu:22.04では必要ない事は分かった。

この状態でビルドしインストールすると、それは成功するけれど、実行すると Segmentation fault が発生する。

root@c40eaf3febd7:/opt/ng/evogym# python3.8 examples/gym_test.py
Using Evolution Gym Simulator v2.2.5
Error initializing GLFW.
Segmentation fault

作業時間を取れなかったので一旦ここで切り上げて、別の日に続きを行う事にした。

別の日に作業と言うと手が付かなくなりがちで、実際に続きの作業ができたのは2週間ぐらい経ってからだった。以前の作業内容はほとんど忘れていたため、再度ジョブを実行し問題の調査からはじめた。ジョブを実行するとあいかわらず失敗する。よく見るとapt-getで失敗していた。以前はこの状態にはならなかったはずだけれど、とりあえず何も考えず修正する事にした。Github Actionsの設定を確認したところ、CIではaptリポジトリの更新をしていなかった。Github ActionsのUbuntuでこれが必要なのかどうはは分からないけれど、通常の運用ではリポジトリのインデックスを更新しないと、正しいパッケージを取得できない。インデックスを更新しても害はないはずなので、とりあえず更新する事にして .github/workflows/test.yml に一行追加(2行か)する事にした。これによりapt-getで失敗する問題は解消した。

      - name: Update deb repository
        run: sudo apt-get update

次はgymのインストールに失敗する問題に取り組む事にした。Evolution Gymで使用しているgymのバージョンは0.19.0だが、以前の調査でこのバージョンはインストールできない事が分かっていた。gymのsetup.pyは extra_require の設定の記述に問題があり、pip installできない状態になっていた。では以前はどうしてたのかと疑問が湧く。おそらくだけれど以前はインストールできていて、destributeかsetuptoolsか、何かしらのパッケージングに関連するコードの更新によって、処理が厳密になり不正値を受け入れなくなったのだと思う。ただその原因を特定する所までは調査できなかった。 しかもstable-baseline3でもgymを要求していて、Evolution Gymが要求するgymとstable-baseline3が要求するgymのバージョンに齟齬ができていた。Evolution Gymではstable-baseline3を直接importしている箇所は無かったため、Evolution Gymのrequirements.txtからは削除する事にした。

これらの修正はプルリクエストを投げておいた。 https://github.com/EvolutionGym/evogym/pull/30

macOSでインストールするためには、ここからまだいくつか修正する必要がある。1つは、submoduleとなっているGLEWを見つけられずビルドに失敗する問題だ。もう1つは、Eigen関連の型の食い違いによる型エラーだ。どちらもシミュレータのコンパイルに失敗する。つらすぎる。しかも暫定的にビルドできる状態にはできるけれど、その問題の本質的な修正をしようとすると、シミュレータの実装をしっかり読む必要があるし、その他の予備知識も不足していて、太刀打ちするための時間を捻出できそうになかった。

GLEWを見つけられない問題は、おそらくCMakeが保持しているFindGLEW.cmakeの実装の問題なのだけれど、これについても本当に問題と言えるのかどうか判断できなかった。とはいえ、Evolution Gymをビルドできないのは困る。そこでカスタムしたFindGLEW.cmakeを上書きして使用する事にしリポジトリに入れた。この修正もプルリクエストを作成しておいた。

https://github.com/EvolutionGym/evogym/pull/31

Eigen関連の型の食い違いによる型エラーは、コンパイラが指示する通りの型に置き換える事にした。macOSはそれで良いかもしれないけれど、GNU/LinuxやWindowsでは型エラーが発生するという話は聞かなかったため、Cのifdefマクロで環境によって型宣言を変更する事にした。この修正もプルリクエストを作成しておいた。

https://github.com/EvolutionGym/evogym/pull/32

修正が正しいのかどうか結構あやしいけれど、ビルドと実行ができるようになった。このEvolution Gymはとある書籍でも使用しているのだが、プルリクエストを作成したままではなかなか使い勝手がよくないため、リポジトリをフォークしてdevelopブランチに全ての修正を含める事にした。必要に応じて使って欲しい。

https://github.com/oreilly-japan/evogym