GitHub Actions でワークフローを実行するときに git commit
と git push
を実行して GitHub Actions の実行を待つことがよくある.より迅速に実行して,結果を受け取るために「act」を使って GitHub Actions をローカル環境(コンテナ)で実行する仕組みを試してみた.便利だったので紹介しようと思う❗️
当然ながら GitHub Actions を完全再現できてるわけではなく,最終的には GitHub Actions を使うことにはなるけど,特に開発中に頻繁にテストを実行できるのはメリットだと思う.うまく併用しながら開発体験を高めよう👌
github.com
セットアップ
macOS の場合は Homebrew を使って簡単にセットアップできる.他には Chocolatey (Windows) や Bash script も選べる.今回は act 0.2.40
と Docker Desktop 4.16.1 を使う.
$ brew install act
$ act --version
act version 0.2.40
act
コマンドには多くのオプションがある.以下に載せておく.
$ act --help
Run GitHub actions locally by specifying the event name (e.g. `push`) or an action name directly.
Usage:
act [event name to run] [flags]
If no event name passed, will default to "on: push"
If actions handles only one event it will be used as default instead of "on: push"
Flags:
-a, --actor string user that triggered the event (default "nektos/act")
--artifact-server-addr string Defines the address to which the artifact server binds. (default "10.0.0.6")
--artifact-server-path string Defines the path where the artifact server stores uploads and retrieves downloads from. If not specified the artifact server will not start.
--artifact-server-port string Defines the port where the artifact server listens. (default "34567")
-b, --bind bind working directory to container, rather than copy
--bug-report Display system information for bug report
--container-architecture string Architecture which should be used to run containers, e.g.: linux/amd64. If not specified, will use host default architecture. Requires Docker server API Version 1.41+. Ignored on earlier Docker server platforms.
--container-cap-add stringArray kernel capabilities to add to the workflow containers (e.g. --container-cap-add SYS_PTRACE)
--container-cap-drop stringArray kernel capabilities to remove from the workflow containers (e.g. --container-cap-drop SYS_PTRACE)
--container-daemon-socket string Path to Docker daemon socket which will be mounted to containers (default "/var/run/docker.sock")
--container-options string Custom docker container options for the job container without an options property in the job definition
--defaultbranch string the name of the main branch
--detect-event Use first event type from workflow as event that triggered the workflow
-C, --directory string working directory (default ".")
-n, --dryrun dryrun mode
--env stringArray env to make available to actions with optional value (e.g. --env myenv=foo or --env myenv)
--env-file string environment file to read and use as env in the containers (default ".env")
-e, --eventpath string path to event JSON file
--github-instance string GitHub instance to use. Don't use this if you are not using GitHub Enterprise Server. (default "github.com")
-g, --graph draw workflows
-h, --help help for act
--input stringArray action input to make available to actions (e.g. --input myinput=foo)
--input-file string input file to read and use as action input (default ".input")
--insecure-secrets NOT RECOMMENDED! Doesn't hide secrets while printing logs.
-j, --job string run a specific job ID
--json Output logs in json format
-l, --list list workflows
--no-recurse Flag to disable running workflows from subdirectories of specified path in '--workflows'/'-W' flag
--no-skip-checkout Do not skip actions/checkout
-P, --platform stringArray custom image to use per platform (e.g. -P ubuntu-18.04=nektos/act-environments-ubuntu:18.04)
--privileged use privileged mode
-p, --pull pull docker image(s) even if already present
-q, --quiet disable logging of output from steps
--rebuild rebuild local action docker image(s) even if already present
--remote-name string git remote name that will be used to retrieve url of git repo (default "origin")
--replace-ghe-action-token-with-github-com string If you are using replace-ghe-action-with-github-com and you want to use private actions on GitHub, you have to set personal access token
--replace-ghe-action-with-github-com stringArray If you are using GitHub Enterprise Server and allow specified actions from GitHub (github.com), you can set actions on this. (e.g. --replace-ghe-action-with-github-com =github/super-linter)
-r, --reuse don't remove container(s) on successfully completed workflow(s) to maintain state between runs
--rm automatically remove container(s)/volume(s) after a workflow(s) failure
-s, --secret stringArray secret to make available to actions with optional value (e.g. -s mysecret=foo or -s mysecret)
--secret-file string file with list of secrets to read from (e.g. --secret-file .secrets) (default ".secrets")
--use-gitignore Controls whether paths specified in .gitignore should be copied into container (default true)
--userns string user namespace to use
-v, --verbose verbose output
--version version for act
-w, --watch watch the contents of the local repo and run when files change
-W, --workflows string path to workflow file(s) (default "./.github/workflows/")
今回使うサンプルワークフロー
今回はサンプルとして,Python で実装した FizzBuzz コードに対して Flake8 と pytest を実行するワークフローを使う.GitHub Actions の「Starter Workflows」として公開されている python-package.yml
をベースに .github/workflows/test.yaml
を用意した.
name: Python package
on:
push:
- master
pull_request:
- master
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.8', '3.9', '3.10']
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest
github.com
act
コマンドを試す
さっそく act
コマンドを試していく❗️
act --list
コマンド
act --list
コマンドを実行するとワークフロー一覧を確認できる.
$ act --list
Stage Job ID Job name Workflow name Workflow file Events
0 build build Python package test.yaml push,pull_request
act
コマンド(初回実行)
act
コマンドを実行するとワークフローを実行できる.初回実行の場合は実行時に使う Docker Image を Large / Medium / Micro から選ぶ.今回は Medium を選んだ.すると,自動的に ~/.actrc
という設定ファイルが作られて,デフォルト設定として使えるようになる..actrc
をリポジトリごとに作って設定を上書きすることもできる.
$ act
? 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
参考までに Large / Medium / Micro それぞれを選んだときに自動的に作られた ~/.actrc
の設定ファイルを以下に載せておく.
Micro
-P ubuntu-latest=node:16-buster-slim
-P ubuntu-22.04=node:16-bullseye-slim
-P ubuntu-20.04=node:16-buster-slim
-P ubuntu-18.04=node:16-buster-slim
Medium
-P ubuntu-latest=catthehacker/ubuntu:act-latest
-P ubuntu-22.04=catthehacker/ubuntu:act-22.04
-P ubuntu-20.04=catthehacker/ubuntu:act-20.04
-P ubuntu-18.04=catthehacker/ubuntu:act-18.04
Large
-P ubuntu-latest=catthehacker/ubuntu:full-latest
-P ubuntu-latest=catthehacker/ubuntu:full-20.04
-P ubuntu-18.04=catthehacker/ubuntu:full-18.04
なお,act 0.2.40 までは Micro を選んだときに作られる設定ファイルが間違っていて,以下のプルリクエストを出して直しておいた.既にリリースされている act 0.2.41 で直っている✌️
github.com
今回のワークフローでは runs-on: ubuntu-latest
と設定しているため,Medium だと catthehacker/ubuntu:act-latest
イメージを使ってワークフローが実行される.現時点だと ubuntu-latest
は ubuntu-22.04
を参照しているため,明示的に -P ubuntu-latest=catthehacker/ubuntu:act-22.04
と設定しておくのも良いかと〜
github.com
act
コマンド
改めて act
コマンドを実行するとワークフローを実行できる.今回は matrix
を使って Python 3.8 / 3.9 / 3.10 を並列実行するため,実行ログには以下の3種類が混在する(見にくいため順番は入れ替えて載せている).また pip install
の実行ログや pytest
実行ログも表示されるため,標準出力は非常に多くなってしまう💦
build-1
: Python 3.8
build-2
: Python 3.9
build-3
: Python 3.10
$ act
(中略)
[Python package/build-1] 🧪 Matrix: map[python-version:3.8]
[Python package/build-2] 🧪 Matrix: map[python-version:3.9]
[Python package/build-3] 🧪 Matrix: map[python-version:3.10]
[Python package/build-1] ✅ Success - Main actions/checkout@v3
[Python package/build-2] ✅ Success - Main actions/checkout@v3
[Python package/build-3] ✅ Success - Main actions/checkout@v3
[Python package/build-1] ✅ Success - Main Set up Python 3.8
[Python package/build-2] ✅ Success - Main Set up Python 3.9
[Python package/build-3] ✅ Success - Main Set up Python 3.10
[Python package/build-1] ✅ Success - Main Install dependencies
[Python package/build-2] ✅ Success - Main Install dependencies
[Python package/build-3] ✅ Success - Main Install dependencies
[Python package/build-1] ✅ Success - Main Lint with flake8
[Python package/build-2] ✅ Success - Main Lint with flake8
[Python package/build-3] ✅ Success - Main Lint with flake8
[Python package/build-1] ✅ Success - Main Test with pytest
[Python package/build-2] ✅ Success - Main Test with pytest
[Python package/build-3] ✅ Success - Main Test with pytest
[Python package/build-1] ✅ Success - Post Set up Python 3.8
[Python package/build-2] ✅ Success - Post Set up Python 3.9
[Python package/build-3] ✅ Success - Post Set up Python 3.10
[Python package/build-1] 🏁 Job succeeded
[Python package/build-2] 🏁 Job succeeded
[Python package/build-3] 🏁 Job succeeded
act --quiet
コマンド
標準出力を "多少" 減らすときは --quiet
オプションを組み合わせて使う.pip install
の実行ログや pytest
実行ログを非表示にできる.それでもまだ多いけど〜
$ act --quiet
(中略)
[Python package/build-1] 🧪 Matrix: map[python-version:3.8]
[Python package/build-2] 🧪 Matrix: map[python-version:3.9]
[Python package/build-3] 🧪 Matrix: map[python-version:3.10]
[Python package/build-1] ✅ Success - Main actions/checkout@v3
[Python package/build-2] ✅ Success - Main actions/checkout@v3
[Python package/build-3] ✅ Success - Main actions/checkout@v3
[Python package/build-1] ✅ Success - Main Set up Python 3.8
[Python package/build-2] ✅ Success - Main Set up Python 3.9
[Python package/build-3] ✅ Success - Main Set up Python 3.10
[Python package/build-1] ✅ Success - Main Install dependencies
[Python package/build-2] ✅ Success - Main Install dependencies
[Python package/build-3] ✅ Success - Main Install dependencies
[Python package/build-1] ✅ Success - Main Lint with flake8
[Python package/build-2] ✅ Success - Main Lint with flake8
[Python package/build-3] ✅ Success - Main Lint with flake8
[Python package/build-1] ✅ Success - Main Test with pytest
[Python package/build-2] ✅ Success - Main Test with pytest
[Python package/build-3] ✅ Success - Main Test with pytest
[Python package/build-1] ✅ Success - Post Set up Python 3.8
[Python package/build-2] ✅ Success - Post Set up Python 3.9
[Python package/build-3] ✅ Success - Post Set up Python 3.10
[Python package/build-1] 🏁 Job succeeded
[Python package/build-2] 🏁 Job succeeded
[Python package/build-3] 🏁 Job succeeded
act --reuse
コマンド
ワークフロー実行時に構築するイメージを再利用する場合は --reuse
オプションを組み合わせて使う.実行時間は多少早くなる.
$ act --reuse
act --watch
コマンド
--watch
オプションを使うとコードやワークフロー設定の変更を検知して,自動的にワークフローを再実行できる.ただし,実際に試してみると,1度テストが落ちると再実行されず,挙動に不安があった🌀
$ act --watch
(中略)
[Python package/build-1] ❌ Failure - Main Test with pytest
[Python package/build-2] ❌ Failure - Main Test with pytest
[Python package/build-3] ❌ Failure - Main Test with pytest
act --env-file
と act --secret-file
コマンド
ワークフローに「環境変数」や「シークレット」を設定する場合,以下のように --env-file
や --secret-file
オプションを使ってファイルを読み込める.直接設定するなら --env
や --secret
オプションも使えるけど,特にシークレットはファイルを読み込むのが良さそう.
$ act --env-file my.env
$ act --secret-file my.secrets
act pull_request
と act schedule
コマンド
実は act
コマンドを実行すると GitHub に対する push
イベントをトリガーするワークフローを実行している.例えば,プルリクエスト時に一部異なるワークフローを実行しているような場合は act pull_request
コマンドを実行すると pull_request
イベントをトリガーするワークフローを実行できる.スケジュール実行をしているような場合は act schedule
コマンドを実行すると schedule
イベントをトリガーするワークフローを実行できる.
on:
push:
branches:
- master
pull_request:
- master
もしワークフローの中で github.event.pull_request.*
などのイベントプロパティに依存している場合は --eventpath
オプションを組み合わせる.詳しくは Wiki の Beginner's guide に載っている.
github.com
まとめ
GitHub Actions のワークフローをローカル環境で実行できる「act」を試した❗️
調べたところ「act」は GitHub Blog でも紹介されていた.
github.blog
実際に試してみて act は便利だったけど,当然ながら GitHub Actions を完全再現できてるわけではなく,例えば「実行できる環境が Ubuntu 限定」や,前に紹介した GitHub Actions の「reusable workflow(ワークフローの再利用)未対応」などは気にしておく必要があると思う.あとワークフローがエラーになって再試行で直るなど不安定な挙動もあって,もう少し使ってみようと思う🌀
$ act
Error: remote reusable workflows are currently not supported (see https://github.com/nektos/act/issues/826 for updates)
kakakakakku.hatenablog.com