フラミナル

考え方や調べたことを書き殴ります。IT技術系記事多め

【新規ツール探し】GitHub Actionsを最速テストできる Act「簡単に動かせすぎてビビった」

  • 記事作成日:2022/12/02

情報

名前 URL
Github https://github.com/nektos/act
公式サイト
デモサイト
開発母体 Casey Lee 氏
version 0.2.34
言語 Go
価格 無料
ライセンス MIT

何ができるもの?

GitHub Actions をローカルで実行できる

これにより以下ができます。

  • ローカルでテスト可能
  • Makefile の代わりに GitHub Actions がローカルで使える

動作の流れ

  • act でコンテナを起動
  • ローカル(~/.cache/act) に各プラグイン(actions/checkout@v2など)を Git clone
  • コンテナに docker cp してコピー
  • 各プラグインの action.yml をみて、プラグインを実行して処理を行う

使い方

Docker Desktop を入れておく

brew install act

or

curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash

デモ

❯ git clone git@github.com:cplee/github-actions-demo.git
Cloning into 'github-actions-demo'...
remote: Enumerating objects: 99, done.
remote: Counting objects: 100% (35/35), done.
remote: Compressing objects: 100% (20/20), done.
remote: Total 99 (delta 22), reused 15 (delta 15), pack-reused 64
Receiving objects: 100% (99/99), 89.70 KiB | 612.00 KiB/s, done.
Resolving deltas: 100% (31/31), done.
❯ cd github-actions-demo/

M1 mac だと怒られたので --container-architecture linux/amd64 をつけます。

❯ act -l
WARN  ⚠ You are using Apple M1 chip and you have not specified container architecture, you might encounter issues while running act. If so, try running it with '--container-architecture linux/amd64'. ⚠  
Stage  Job ID  Job name  Workflow name  Workflow file  Events
0      test    test      CI             main.yml       push  
❯ act -l --container-architecture linux/amd64
❯ alias act="act --container-architecture linux/amd64"

test job の実施。(yaml に定義されている名前がそのまま指定できるようです)

❯ cat .github/workflows/main.yml
name: CI
on: push

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v1
    - run: npm install
    - run: npm test
❯ act -j test --container-architecture linux/amd64
? Please choose the default image you want to use with act:

  - Large size image: +20GB Docker image, includes almost all tools used on GitHub Actions (IMPORTANT: currently only ubuntu-18.04 platform is available)
  - Medium size image: ~500MB, includes only necessary tools to bootstrap actions and aims to be compatible with all actions
  - Micro size image: <200MB, contains only NodeJS required to bootstrap actions, doesn't work with all actions

Default image and other options can be changed manually in ~/.actrc (please refer to https://github.com/nektos/act#configuration for additional information about file structure) Medium
[CI/test] 🚀  Start image=catthehacker/ubuntu:act-latest
[CI/test]   🐳  docker pull image=catthehacker/ubuntu:act-latest platform=linux/amd64 username= forcePull=false
[CI/test]   🐳  docker create image=catthehacker/ubuntu:act-latest platform=linux/amd64 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[CI/test]   🐳  docker run image=catthehacker/ubuntu:act-latest platform=linux/amd64 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[CI/test]   ☁  git clone 'https://github.com/actions/setup-node' # ref=v1
[CI/test] ⭐ Run Main actions/checkout@v2
[CI/test]   🐳  docker cp src=/Users/myhome/Cording/github-actions-demo/. dst=/Users/myhome/Cording/github-actions-demo
[CI/test]   ✅  Success - Main actions/checkout@v2
[CI/test] ⭐ Run Main actions/setup-node@v1
[CI/test]   🐳  docker cp src=/Users/myhome/.cache/act/actions-setup-node@v1/ dst=/var/run/act/actions/actions-setup-node@v1/
[CI/test]   🐳  docker exec cmd=[node /var/run/act/actions/actions-setup-node@v1/dist/index.js] user= workdir=
[CI/test]   💬  ::debug::isExplicit: 
[CI/test]   💬  ::debug::explicit? false
[CI/test]   💬  ::debug::isExplicit: 12.22.12
[CI/test]   💬  ::debug::explicit? true
[CI/test]   💬  ::debug::isExplicit: 16.18.1
[CI/test]   💬  ::debug::explicit? true
[CI/test]   💬  ::debug::evaluating 0 versions
[CI/test]   💬  ::debug::match not found
[CI/test]   💬  ::debug::evaluating 550 versions
[CI/test]   💬  ::debug::matched: v10.24.1
[CI/test]   💬  ::debug::isExplicit: 10.24.1
[CI/test]   💬  ::debug::explicit? true
[CI/test]   💬  ::debug::checking cache: /opt/hostedtoolcache/node/10.24.1/x64
[CI/test]   💬  ::debug::not found
[CI/test]   💬  ::debug::Downloading https://nodejs.org/dist/v10.24.1/node-v10.24.1-linux-x64.tar.gz
[CI/test]   💬  ::debug::Destination /tmp/830356d4-4a22-4ae9-b33c-0a679d4ff4b6
[CI/test]   💬  ::debug::download complete
[CI/test]   💬  ::debug::Checking tar --version
[CI/test]   💬  ::debug::tar (GNU tar) 1.30%0ACopyright (C) 2017 Free Software Foundation, Inc.%0ALicense GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.%0AThis is free software: you are free to change and redistribute it.%0AThere is NO WARRANTY, to the extent permitted by law.%0A%0AWritten by John Gilmore and Jay Fenlason.
| [command]/usr/bin/tar xz --warning=no-unknown-keyword -C /tmp/d6128a59-dfca-4df2-b29d-13b4910de9a7 -f /tmp/830356d4-4a22-4ae9-b33c-0a679d4ff4b6
[CI/test]   💬  ::debug::Caching tool node 10.24.1 x64
[CI/test]   💬  ::debug::source dir: /tmp/d6128a59-dfca-4df2-b29d-13b4910de9a7/node-v10.24.1-linux-x64
[CI/test]   💬  ::debug::destination /opt/hostedtoolcache/node/10.24.1/x64
[CI/test]   💬  ::debug::finished caching tool
| [command]/opt/hostedtoolcache/node/10.24.1/x64/bin/node --version
| v10.24.1
| [command]/opt/hostedtoolcache/node/10.24.1/x64/bin/npm --version
| 6.14.12
[CI/test]   ❓  ##[add-matcher]/run/act/actions/actions-setup-node@v1/.github/tsc.json
[CI/test]   ❓  ##[add-matcher]/run/act/actions/actions-setup-node@v1/.github/eslint-stylish.json
[CI/test]   ❓  ##[add-matcher]/run/act/actions/actions-setup-node@v1/.github/eslint-compact.json
[CI/test]   ✅  Success - Main actions/setup-node@v1
[CI/test] ⭐ Run Main npm install
[CI/test]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/2] user= workdir=
| added 280 packages from 643 contributors and audited 280 packages in 21.497s
| 
| 24 packages are looking for funding
|   run `npm fund` for details
| 
| found 25 vulnerabilities (9 moderate, 13 high, 3 critical)
|   run `npm audit fix` to fix them, or `npm audit` for details
[CI/test]   ✅  Success - Main npm install
[CI/test] ⭐ Run Main npm test
[CI/test]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/3] user= workdir=
| 
| > github-actions-demo@1.0.0 test /Users/myhome/Cording/github-actions-demo
| > mocha ./tests --recursive
| 
| 
| 
|   GET /
|     ✓ should respond with hello world (231ms)
| 
| 
|   1 passing (286ms)
| 
[CI/test]   ✅  Success - Main npm test
[CI/test] 🏁  Job succeeded

オリジナルの CI を足してみる

my-testの追加 checkout するだけのもの。

name: CI
on: push

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v1
    - run: npm install
    - run: npm test

  my-test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
❯ act -l
Stage  Job ID   Job name  Workflow name  Workflow file  Events
0      test     test      CI             main.yml       push  
0      my-test  my-test   CI             main.yml       push  

❯ act -j my-test
[CI/my-test] 🚀  Start image=catthehacker/ubuntu:act-latest
[CI/my-test]   🐳  docker pull image=catthehacker/ubuntu:act-latest platform=linux/amd64 username= forcePull=false
[CI/my-test]   🐳  docker create image=catthehacker/ubuntu:act-latest platform=linux/amd64 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[CI/my-test]   🐳  docker run image=catthehacker/ubuntu:act-latest platform=linux/amd64 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[CI/my-test] ⭐ Run Main actions/checkout@v2
[CI/my-test]   🐳  docker cp src=/Users/myhome/Cording/github-actions-demo/. dst=/Users/myhome/Cording/github-actions-demo
[CI/my-test]   ✅  Success - Main actions/checkout@v2
[CI/my-test] 🏁  Job succeeded

できた。 次に別ファイルを作ってみる。

name: CI
on: push

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v1
    - run: npm install
    - run: npm test

  my-test:
    runs-on: ubuntu-latest
    steps:
    - run: |
        echo "this is copy file"

同じ名前でもファイルのカラムで判別できる

❯ act -l
Stage  Job ID   Job name  Workflow name  Workflow file  Events
0      my-test  my-test   CI             main.yml       push  
0      test     test      CI             main.yml       push  
0      test     test      CI             new_ci.yml     push  
0      my-test  my-test   CI             new_ci.yml     push  

❯ act -g
 ╭─────────╮ ╭──────╮ ╭──────╮ ╭─────────╮
 │ my-test │ │ test │ │ test │ │ my-test │
 ╰─────────╯ ╰──────╯ ╰──────╯ ╰─────────╯

同じ名前のテストがあると片方が実行された後にエラーになる。

❯ act -j my-test
[CI/my-test] 🚀  Start image=catthehacker/ubuntu:act-latest
[CI/my-test] 🚀  Start image=catthehacker/ubuntu:act-latest
[CI/my-test]   🐳  docker pull image=catthehacker/ubuntu:act-latest platform=linux/amd64 username= forcePull=false
[CI/my-test]   🐳  docker pull image=catthehacker/ubuntu:act-latest platform=linux/amd64 username= forcePull=false
[CI/my-test]   🐳  docker create image=catthehacker/ubuntu:act-latest platform=linux/amd64 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[CI/my-test]   🐳  docker create image=catthehacker/ubuntu:act-latest platform=linux/amd64 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[CI/my-test]   🐳  docker run image=catthehacker/ubuntu:act-latest platform=linux/amd64 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[CI/my-test] ⭐ Run Main actions/checkout@v2
[CI/my-test]   🐳  docker cp src=/Users/myhome/Cording/github-actions-demo/. dst=/Users/myhome/Cording/github-actions-demo
[CI/my-test]   ✅  Success - Main actions/checkout@v2
[CI/my-test] 🏁  Job succeeded
Error: failed to create container: 'Error response from daemon: Conflict. The container name "/act-CI-my-test" is already in use by container "0fc4293aa7cc707268fabfec2251fbcd75540aab84af8b120dcb147192d2ca59". You have to remove (or rename) that container to be able to reuse that name.'

-W パス名 で指定すると、指定したパスのファイルを読み込む。

❯ act -j my-test -W .github/workflows/new_ci.yml
[CI/my-test] 🚀  Start image=catthehacker/ubuntu:act-latest
[CI/my-test]   🐳  docker pull image=catthehacker/ubuntu:act-latest platform=linux/amd64 username= forcePull=false
[CI/my-test]   🐳  docker create image=catthehacker/ubuntu:act-latest platform=linux/amd64 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[CI/my-test]   🐳  docker run image=catthehacker/ubuntu:act-latest platform=linux/amd64 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[CI/my-test] ⭐ Run Main echo "this is copy file"
[CI/my-test]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/0] user= workdir=
| this is copy file
[CI/my-test]   ✅  Success - Main echo "this is copy file" <- ここが変わった
[CI/my-test] 🏁  Job succeeded

イメージの差し替え

基本的には動いたのですが、GitHub 公式で使っている Ubuntu イメージに比べて軽量なので動かないものもありました。 ということで公式に書かれているイメージを差し替える方法。(重いからか全然進まない…)

act -j generate-schema -P ubuntu-20.04=ghcr.io/catthehacker/ubuntu:full-20.04

利用シーン

  • GitHub Actions を手軽に開発したい時(毎回 Push する必要がないので楽ちん)
  • GitHub Actions をテストしたい時

登場背景

by DeepL

GitHub Actionsをローカルで実行しよう!なぜこんなことをしたいのでしょうか?理由はふたつあります。

高速なフィードバック-.github/workflows/ファイルに加えた変更(あるいは GitHub に組み込まれたアクションの変更)をテストするために毎回 commit/push する必要はなく、act を使ってローカルでアクションを実行することができます。環境変数や ファイルシステムはすべて GitHub が提供するものと同じに設定されています。 ローカルタスクランナー- 私は作ることが好きです。しかし、同じことを繰り返すのも嫌だ。actを使えば、.github/workflows/に定義されたGitHub ActionsをMakefileの代わりに使うことができます!

気にすること

利用は非常に簡単だが、Nearly Equal なことを理解する必要あり。 エラーで落ちる場合は act 側の調整と、GitHub Actions の yaml 側の対応が必要。