先頭を 歩く者には 落とし穴 ハマっては埋め ハマっては埋め
どうも、かわしんです。先駆者ってのはかっこいいとは思いますが、僕自身は新しい技術は流行り始めてから少し待って、落とし穴が一通り埋め尽くされたあたりで使い始めて爆速で開発するのが好きです。
さて、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 が対応しています。
環境変数に 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 へはお問い合わせでフィードバックしておきました。
なぜか 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 はセマンティクスバージョニングに対応していない
webfactory/ssh-agent
の README には webfactory/ssh-agent@v0.1
と指定するように書いてありました。(現在は修正されています)
タグは v0.1.0
と v0.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>.services
は command
の差し替えをサポートしていません。また、設定ファイルのマウントをしようと思いましたが、ファイルやディレクトリのマウントはできるものの Docker コンテナの起動時はまっさらなイメージで起動し steps
の実行はその後であるため設定ファイルを差し込むことが不可能でした。
設定できるのは環境変数だけであるため、環境変数で設定できない Docker イメージは全て滅びろ という Github の強いメッセージが伝わってきます。
解決策としては、自分で CMD
を差し替えたり設定ファイルを注入した Docker イメージを作成し、 DockerHub などに公開してそれを利用するというものになります。面倒臭いです。Github Actions のためだけに DockerHub にリポジトリを作って Dockerfile を書いてって、本当にめんどくさかったです。これも、Github にフィードバックしておきました。
CI 上でデバッグする方法
これが便利でした。注意点としては、sudo
コマンドに依存しているため sudo
がない環境では apt-get install -y sudo
などをしてインストールする必要があります。
まとめ
パブリックベータだけあって、ちょっと変なことをしようとすると色々不便でした。が、Github Actions 自体の設計や並列性などは素晴らしいと思うのでこれからどんどん発展していって欲しいです。
現場からは以上です。
-
https://github.com/pypa/pipenv の
Installing from git:
の項目を参照してください。↩