kawasin73のブログ

技術記事とかいろんなことをかくブログです

Github Actions でハマった点と解決方法

先頭を 歩く者には 落とし穴 ハマっては埋め ハマっては埋め

どうも、かわしんです。先駆者ってのはかっこいいとは思いますが、僕自身は新しい技術は流行り始めてから少し待って、落とし穴が一通り埋め尽くされたあたりで使い始めて爆速で開発するのが好きです。

さて、Github Actions が最近パブリックベータになり、プライベートリポジトリで利用してみました。その上で、結構ハマったりめんどくさかったりした点があったので解決策とともに共有したいと思います。

なお、Github Actions がどのようなものなのかの説明はみなさんご存知だと思うので省略させていただきます。1

プライベートリポジトリのインストール

今回は Python パッケージで Pipenv を利用してパッケージをインストールしていたのですが、インストールするパッケージのなかに Github 上のプライベートリポジトリからダウンロードするものがありました。鍵の情報を Pipfile に記載したくはないので https ではなく ssh を利用してダウンロードするようにしていました。2

$ pipenv install git+ssh://git@<location>:<user_or_organization>/<repository>@<branch_or_tag>#<package_name>

そのため、CI 上での pipenv install でのパッケージのインストールにはプライベートリポジトリへのアクセス権を ssh に設定する必要があります。

SSH 鍵の設定はこの Github Action が対応しています。

github.com

環境変数に pem 方式でテキスト化された秘密鍵を設定すると ssh-add で SSH Agent に設定 し、Github の公開鍵を known_hosts ファイルに追記する というものです。公開鍵をダウンロードする Github リポジトリの Deploy Keys に設定すればダウンロードできるようになります。

しかし、このリポジトリには以下の問題があります。

そもそも第三者の Action である

この Action は webfactory というドイツの会社が公開しているのですが第三者であるため、秘密鍵を扱う Action としては信頼性に欠ける というものがあります。

現状の Action の内容はコードを読んだ限り問題はないのですが、この会社が将来的に Action の内容を書き換えて Force Push されても利用者は気づくことができません。秘密鍵の権限は限定されているため影響は限られますが、好ましいことではありません。

短期的な解決策としてはこのリポジトリを fork して改竄が不可能なようにすることです。しかし、この方法は元リポジトリがアップデートされるたびに追従しないといけなかったり、そもそも利用者全員が fork するということ自体が面倒で理想的ではありません。

根本的な解決策としては、この Action を公式の Action に取り込んでもらうことです。Github が管理する Action であれば信頼できますし、そもそも秘密鍵Github に登録しているので Github がこの Action を改竄するメリットがありません。公式の Action は次の Organization で公開されています。

github.com

ここに追加されると嬉しいです。一応 Github へはお問い合わせでフィードバックしておきました。

なぜか git clone できない

意気揚々と CI を回してみますが、pipenv install をしても private リポジトリのインストールがされません。(これは愚痴なのですが、インストールに失敗しているくせに pipenv install は成功である 0 コードを返すためパッケージのインストールに失敗していることに気づけません。この後の Flake8 がコケる理由がこれだったのですが、パッケージがインストールされていないことに気づくまで時間を無駄にしました。 Pipenv のパッケージマネージャとしての品質の低さにはうんざりです。 3

さて、内部で行われている git clone を直接行ってみると以下のエラーが表示されます。

Host key verification failed.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
##[error]Process completed with exit code 128.

これはサーバ鍵(Github 側の鍵)の検証に失敗しているという意味です。known_hosts にあらかじめ ssh-agent Action が Github の公開鍵を記載しているため、問題ないはずなのですが失敗します。

そこで独自に known_hosts を以下のコマンドで上書きしてみましたが git clone に失敗します。

ssh-keyscan github.com > $HOME/.ssh/known_hosts

おそらく git clone でみている known_hosts ファイルが別の場所にあるのだと思うのですが、それを探す気力が無くなっていたので サーバ鍵の検証を無視する ことにして解決しました。

GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" pipenv install -v --system --dev --skip-lock --ignore-pipfile

GIT_SSH_COMMAND という環境変数git が利用する ssh コマンドを差し替えることができます。今回は Github が運営する CI から Githubリポジトリgit clone するため中間者攻撃は考えにくいです。そのため、サーバ鍵の検証をスキップしてもセキュリティ上のリスクは小さいと考えて許容しました。

actions はセマンティクスバージョニングに対応していない

github.com

webfactory/ssh-agent の README には webfactory/ssh-agent@v0.1 と指定するように書いてありました。(現在は修正されています)

タグは v0.1.0v0.1.1 があるのですが、Github Actions はセマンティクスバージョニングには対応しておらず完全一致で Action を決めているようです。

We do not currently apply any semantic versioning semantics, we only match a literal release tag. However we may revisit this policy during the beta period.

Solved: Version numbering for Actions - GitHub Community Forum

README を信用したばっかりにこれで結構ハマりました。注意しましょう。

jobs.<job_id>.services の docker コンテナが不便

docker-compose と同じように jobs.<job_id>.services に設定することで複数の Docker コンテナを起動できます。この仕組みを利用してテストに必要な MySQL サーバを起動していたのですが、非常に使いにくかったです。

手元の docker-compose では utf8mb4 に対応するために command:mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci と設定して Docker コンテナの実行コマンドを差し替えていました。

しかし、jobs.<job_id>.servicescommand の差し替えをサポートしていません。また、設定ファイルのマウントをしようと思いましたが、ファイルやディレクトリのマウントはできるものの Docker コンテナの起動時はまっさらなイメージで起動し steps の実行はその後であるため設定ファイルを差し込むことが不可能でした。

設定できるのは環境変数だけであるため、環境変数で設定できない Docker イメージは全て滅びろ という Github の強いメッセージが伝わってきます。

解決策としては、自分で CMD を差し替えたり設定ファイルを注入した Docker イメージを作成し、 DockerHub などに公開してそれを利用するというものになります。面倒臭いです。Github Actions のためだけに DockerHub にリポジトリを作って Dockerfile を書いてって、本当にめんどくさかったです。これも、Github にフィードバックしておきました。

CI 上でデバッグする方法

github.com

これが便利でした。注意点としては、sudo コマンドに依存しているため sudo がない環境では apt-get install -y sudo などをしてインストールする必要があります。

まとめ

パブリックベータだけあって、ちょっと変なことをしようとすると色々不便でした。が、Github Actions 自体の設計や並列性などは素晴らしいと思うのでこれからどんどん発展していって欲しいです。

現場からは以上です。