パパエンジニアのアウトプット帳

30歳に突入した1児のパパエンジニアのブログ

actを使うとGithub Actionsのワークフロー定義をローカルで確認しながらやれて便利

お仕事でGithub Actionsを利用してプルリクのラベル自動付与するworkflowを定義するときに、ローカルである程度確認作業とかできないかなーと思っていたらactを思い出したので使ってみました。

actとは

github.com Dockerを利用して.github/workflowsに沿ったワークフローをローカルでもシュッと実行できるようにしているみたいです。

Let's Try

Github Actionsのworkflowの書き方は公式ドキュメントあるのでそれ読めばわかるはずです。 docs.github.com

$ vi .github/workflows/on_pull_request.yml
----以下追加-----
name: sample workflow on pull-request

on:
  pull_request:

jobs:
  helloWorld:
    name: Hello World Job
    runs-on: ubuntu-18.04
    run: echo "Hello World"

保存したらpull_requestイベントが発火した時のworkflowを確認してみます。
actコマンドの実行方法は act イベント名 オプション です。
オプションにlを指定すると実行されるworkflowの一覧が出力されます。

$ act -l pull_request
 ╭─────────────────╮
 │ Hello World Job │
 ╰─────────────────╯

違うイベントにしてみると、実行されるworkflowがないことがわかります。
※イベント名を省略するとpushイベントがデフォルトになっているっぽいです

$ act -l push

試しにもう一つjobを足してみると

$ vi .github/workflows/on_pull_request.yml
-----
name: sample workflow on pull-request

on:
  pull_request:

jobs:
  helloWorld:
    name: Hello World Job
    runs-on: ubuntu-18.04
    run: echo "Hello World"
  HogeFuga:
    name: Hoge Fuga Job
    runs-on: ubuntu-18.04
    run: echo "hoge fuga"

$ act -l pull_request
 ╭─────────────────╮ ╭───────────────╮
 │ Hello World Job │ │ Hoge Fuga Job │
 ╰─────────────────╯ ╰───────────────╯

jobが2つになりました。
さらに、HelloWorld→HogeFugaの順で実行するように定義すると

$ vi .github/workflows/on_pull_request.yml
-----
name: sample workflow on pull-request

on:
  pull_request:

jobs:
  helloWorld:
    name: Hello World Job
    runs-on: ubuntu-18.04
    run: echo "Hello World"
  HogeFuga:
    name: Hoge Fuga Job
    runs-on: ubuntu-18.04
    needs: helloWorld # ←追加
    run: echo "hoge fuga"

$ act -l pull_request
 ╭─────────────────╮
 │ Hello World Job │
 ╰─────────────────╯
         ⬇
  ╭───────────────╮
  │ Hoge Fuga Job │
  ╰───────────────╯

ちゃんと依存関係も反映された表示がされます!
分かりやすい!!

dry-runモード

nオプションを付けるとdry-runで実行されます。

$ act pull_request -n
WARN[0000] unable to get git repo: unable to find git repo
WARN[0000] unable to get git revision: unable to find git repo
WARN[0000] unable to get git ref: unable to find git repo
WARN[0000] unable to get git repo: unable to find git repo
WARN[0000] unable to get git revision: unable to find git repo
WARN[0000] unable to get git ref: unable to find git repo
*DRYRUN* [sample workflow on pull-request/Hello World Job] 🚀  Start image=node:12.6-buster-slim
WARN[0000] unable to get git repo: unable to find git repo
WARN[0000] unable to get git revision: unable to find git repo
WARN[0000] unable to get git ref: unable to find git repo
*DRYRUN* [sample workflow on pull-request/Hello World Job]   🐳  docker run image=node:12.6-buster-slim entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
*DRYRUN* [sample workflow on pull-request/Hoge Fuga Job  ] 🚀  Start image=node:12.6-buster-slim
WARN[0000] unable to get git repo: unable to find git repo
WARN[0000] unable to get git revision: unable to find git repo
WARN[0000] unable to get git ref: unable to find git repo
*DRYRUN* [sample workflow on pull-request/Hoge Fuga Job  ]   🐳  docker run image=node:12.6-buster-slim entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]

(ちょっと元がechoの表示がないので実行されていないは分かりにくいですが、確かにdry-runされています)

イベント発火時にどんな情報が来るか

実際にGithub Actionsを利用する場合はさらに詳しい情報を見てやる/やらないしたりすると思います。
(例えば、draftプルリクの時は実行しないようにするとか)
そんな場合は、下記にevent時に渡ってくる情報がサンプルもあるので、それをactのeオプションで指定すると確認できます。 developer.github.com

試しに、先ほどのworkflowのHogeFugaジョブをdraftプルリクの場合は実行しないようにしてみましょう。

$ vi 
name: sample workflow on pull-request

on:
  pull_request:

jobs:
  helloWorld:
    name: Hello World Job
    runs-on: ubuntu-18.04
    run: echo "Hello World"
  HogeFuga:
    name: Hoge Fuga Job
    runs-on: ubuntu-18.04
    needs: helloWorld
    if: ${{ github.event.pull_request.draft == false }} # ←ifを追加
    run: echo "hoge fuga"

pull_requestのサンプルのpayloadのjsonファイルを用意します。

$ vi sample-pullreq.json

----全部だと多いので抜粋------
{
  "action": "opened",
  "pull_request": {
    "url": "https://api.github.com/repos/Codertocat/Hello-World/pulls/2",
    "draft": true
  }
}

これをeオプションで指定してdry-runしてみます。

$act pull_request -n -e sample-pullreq.json

WARN[0000] unable to get git repo: unable to find git repo
WARN[0000] unable to get git revision: unable to find git repo
WARN[0000] unable to get git ref: unable to find git repo
WARN[0000] unable to get git repo: unable to find git repo
WARN[0000] unable to get git revision: unable to find git repo
WARN[0000] unable to get git ref: unable to find git repo
*DRYRUN* [sample workflow on pull-request/Hello World Job] 🚀  Start image=node:12.6-buster-slim
WARN[0000] unable to get git repo: unable to find git repo
WARN[0000] unable to get git revision: unable to find git repo
WARN[0000] unable to get git ref: unable to find git repo
*DRYRUN* [sample workflow on pull-request/Hello World Job]   🐳  docker run image=node:12.6-buster-slim entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]

先ほどと違って *DRYRUN* [sample workflow on pull-request/Hoge Fuga Job ] が実行されていないのが分かります。

最後に

actを使えば、ローカルでGithub Actionsのworkflowを確認しながら定義することができてとても便利です。
他にも環境変数も渡したりできるので、実際に実行することも可能です。(元々actの作者がローカルでのworkflowを自動化したかったのもあるので当然ですが)
Github Actionsのお供にactはオススメだと思います。

その他

Github Actionsでデバッグするときはクラメソさんの記事のようにsecretsにACTIONS_RUNNER_DEBUGとACTIONS_STEP_DEBUGを設定すると良さげです。
dev.classmethod.jp