GitHub Actions のデバッグをローカルで行う
概要
GitHub Actions で GitHub ホストランナーを使用する場合、パブリックポジトリは無料ですがプライベートリポジトリは従量課金(無料枠あり)です。
ワークフローを編集する際にデバッグしていると結構な時間を消費してしまいます。
そこでデバッグ時は GitHub ホストランナーを使わずに無料で実行する方法を 3 種類紹介します。
nektos/act
言わずと知れたローカル実行ツールです。
すべてを再現することはできませんがコミットを増やさずにデバッグができます。
注意点
-
ubuntu-*
のみサポート - ソフトウェアは指定する Docker イメージ依存、デフォルトのイメージだと色々足りないので
-P
で指定 -
secrets.GITHUB_TOKEN
が未定義なので Personal Access Token を発行し設定が必要 - サービスコンテナ
services
が使えない -
$ACT
を使うと本番との差異が大きくなる
ubuntu-*
しかサポートされていませんが Docker コンテナ上で動かしてくれるのでローカル PC が Windows や Mac でも ubuntu-*
のワークフローが動かせるのはメリット。
セルフホストランナー
ローカル PC に セルフホストランナー をインストールして利用します。
コミットは増えてしまいますが最後に git rebase -i
したらいいでしょう。
正式なランナーなので完全に動作します。
runs-on
を一時的に書き換えて [ self-hosted ]
を指定します。
既存のセルフホストランナーがある場合はラベルを付けると区別できます。
jobs:
build:
runs-on: [ self-hosted, pc ]
注意点
-
runs-on
に設定している OS とローカル PC の OS が異なると実行できないコマンドが多い - ソフトウェアはインストールする必要がある
- ランナー登録用のトークンまたは Personal Access Token を発行し設定が必要
- Windows は PowerShell の実行ポリシーを変更する必要がある
- ランナーにある制約はそのまま(
uses
での Docker コンテナアクションあるいはservices
でのサービスコンテナを使うなら Linux が必要) - OS が同じでもディストリビューションが一致しているとは限らない
ランナーの制約を受けてしまうのが曲者でローカル PC が Windows や Mac だと ubuntu-*
のワークフローを動かせないのがデメリット。
Windows
Windows の場合デフォルトシェルが PowerShell になっています。
スクリプトの実行が許可されていないので 実行ポリシー を変更する必要があります。
Get-ExecutionPolicy
Set-ExecutionPolicy -ExecutionPolicy Bypass
デバッグが終わったら元の値に戻しておきましょう。
セルフホストランナー in Docker
前項のデメリットを解消できないか試みます。
ランナーを含んだ Docker イメージが公開されているのでこちらを利用します。
myoung34/github-runner
Ubuntu ベースのようなので GitHub ホストランナーの ubuntu-*
との差異は少なそうです。
Enterprise にも対応してます。
docker-compose.yml
を作成して実行します。
Docker in Docker になるのでホストの Docker daemon を共有しているようですね。
追加のソフトウェアをインストールしたい場合は Dockerfile を定義して image
を build
に変更しましょう。
version: "3.9"
services:
runner:
image: myoung34/github-runner:latest
environment:
REPO_URL: https://github.com/<org>/<repo>
ACCESS_TOKEN: <Personal Access Token>
RUNNER_WORKDIR: /tmp/runner/work
LABELS: pc
# SELinux システムでは docker コンテナが
# 他の docker コンテナを管理するのを許可するために必要
# security_opt:
# - label:disable
volumes:
- '/var/run/docker.sock:/var/run/docker.sock'
- '/tmp/runner:/tmp/runner'
# docker-in-docker では同じパスがホストとコンテナ内に必要
# docker の mgmt コマンドは docker の外側で走るがパスは内側を期待する
各項目を自分の環境に合わせて書き換えます。
その他オプションは公式ドキュメントを参照してください。
どこかへコミットするなら .env
に定義して環境変数で参照しましょう。
docker-compose run --rm runner
# or
docker-compose up -d
後者でバックグラウンド実行する場合は docker-compose logs -f runner
でログを確認できます。
Windows の Hyper-V モードや Mac の場合 File Sharing の設定が必要な場合があります。
ホストの Docker -> Preferences... -> Resources -> File Sharing に /tmp
がなければ足してください。
コンテナにインストールされている Docker バージョン。
root@c58ce4c18ba7:/actions-runner# grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Ubuntu 20.04.2 LTS"
root@94591e171112:/actions-runner# docker -v
Docker version 20.10.7, build f0df350
root@94591e171112:/actions-runner# docker-compose -v
docker-compose version 1.27.4, build 40524192
Ctrl+C
または docker-compose down
で終了します。
自動的にランナーの登録を解除してくれます。
Docker コンテナアクションや docker
コマンドは動かせるのですが、サービスコンテナを動かすことはできないようで Initialize containers
で失敗します。
ランナーのロジックで弾いてるみたいですね。(このロジック削除してほしい…)
Check whether we are inside a container.
Our container feature requires to map working directory from host to the container.
If we are already inside a container, we will not able to find out the real working direcotry path on the host.
https://github.com/actions/runner/blob/ebadce7958e3f1651b7d956c6a4969e2fc4bd48f/src/Runner.Worker/ContainerOperationProvider.cs#L54-L70
tcardonne/github-runner
tcardonne/github-runner
Ubuntu ベースのようなので GitHub ホストランナーの ubuntu-*
との差異は少なそうです。
myoung34/github-runner と比べると機能が少なかったりバージョンが古かったりするようです。
version: "3.9"
services:
runner:
image: tcardonne/github-runner:latest
environment:
RUNNER_REPOSITORY_URL: ${RUNNER_REPOSITORY_URL}
GITHUB_ACCESS_TOKEN: ${GITHUB_ACCESS_TOKEN}
RUNNER_LABELS: pc
volumes:
- /var/run/docker.sock:/var/run/docker.sock
${***}
の部分を自分の環境に合わせて書き換えます。
.env
に定義しても良いですしデバッグ用途であれば直接書き換えてしまっても良いでしょう。
Mac の場合これだけだとコンテナ内で docker
コマンドを実行したときにエラーになります。
ローカルで動かしている Docker の File Sharing の設定に /home/runner
を追加します。
root@31e878a24a08:/home/runner# docker run --rm -it -v $PWD:/app composer help
docker: Error response from daemon: Mounts denied:
The path /home/runner is not shared from the host and is not known to Docker.
You can configure shared paths from Docker -> Preferences... -> Resources -> File Sharing.
See https://docs.docker.com/docker-for-mac for more info.
ERRO[0000] error waiting for container: context canceled
コンテナ内で使用できる Docker のバージョンは少し古いみたいですね。
root@bb8b1afef2f7:/home/runner# grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Ubuntu 20.04.1 LTS"
root@bb8b1afef2f7:/home/runner# docker -v
Docker version 19.03.13, build 4484c46d9d
root@bb8b1afef2f7:/home/runner# docker-compose -v
docker-compose version 1.27.4, build 40524192
Ctrl+C
で終了した際にランナーの登録が解除されないので手動で強制削除する必要があります。
注意点
- ランナー登録用のトークンまたは Personal Access Token を発行し設定が必要
- サービスコンテナ
services
が使えない - Windows や Mac も可能かもしれませんがイメージの自作からしないといけないので大変そう
- Windows ホストで WSL 1 モードの場合 File Sharing ができず
docker-compose.yml
に定義している/tmp/runner:/tmp/runner
がマウントされない。そのためディレクトリが生成されずマウントを利用する Docker コンテナアクションが動作しない(Hyper-V モードや WSL 2 モードなら動作しそうだが未検証。Mac だと正常に動作する)
その他注意点
GitHub ホストランナー以外の環境では一部のアクションが動かないことがあります。
(GitHub ホストランナーに依存した絶対パスを使ってしまっているケース等、アクション側のバグである可能性あり)
まとめ
機能 | nektos/act | セルフ ホストランナー |
セルフ ホストランナー in Docker |
GitHub ホストランナー |
---|---|---|---|---|
OS runs-on
|
Linux | Linux Win Mac |
Linux | Linux Win Mac |
ローカル PC と 異なる OS runs-on
|
⭕️ | ❌ | ⭕️ | ⭕️ |
コミット&プッシュ | 不要 | 必要 | 必要 | 必要 |
JavaScript アクションuses
|
⭕️ | ⭕️ | ⭕️ | ⭕️ |
Docker コンテナアクションuses
|
⭕️ | ⭕️ Linux ❌ Win, Mac |
⭕️ | ⭕️ Linux ❌ Win, Mac |
サービスコンテナ services
|
❌ | ⭕️ Linux ❌ Win, Mac |
❌ | ⭕️ Linux ❌ Win, Mac |
docker コマンドdocker-compose コマンド |
⭕️ | ⭕️ | ⭕️ | ⭕️ |
GitHub ホストランナー との差異 |
大 | 中 | 小 | - |
料金 | 無料 | 無料 | 無料 | 従量課金 |
Discussion