はじめに
GitHub Actions のワークフローを開発していると、こんな経験はないでしょうか。
- YAML を間違えて push → 失敗 → 修正して push → また失敗…
- トリガーが
mainだけなので feature ブランチで試せない - 動作確認のためだけにコミットが増えていく
本記事では、ワークフローの開発を効率化するツールやテクニックを紹介します。
提案する開発フロー
先に全体像を示します。

ローカルで潰せるものはローカルで潰して、push の回数を減らすのがポイントです。
Step 1: actionlint で静的解析する
actionlint は、GitHub Actions ワークフロー専用の静的チェッカーです。
GitHub - rhysd/actionlint: :octocat: Static checker for GitHub Actions workflow files
:octocat: Static checker for GitHub Actions workflow files - rhysd/actionlint
ワークフローを実行せずに、以下のような問題を検出できます。
- 構文エラー(キー名の誤り等)
${{ }}式の型チェック(存在しないプロパティへのアクセス等)- アクションの inputs/outputs の検証
run:内のシェルスクリプト解析(shellcheck 連携)- スクリプトインジェクションなどのセキュリティチェック
- glob パターン、cron 構文、ランナーラベルの検証
インストールして、リポジトリのルートで実行するだけです。
1❯ brew install actionlint
2
3❯ actionlint
4.github/workflows/build.yml:10:5: "ubuntu-latst" is unknown runner label [runner-label]
5.github/workflows/build.yml:15:21: property "stat" is not defined in object type {conclusion: string; ...} [expression]エラーがなければ何も出力されません。
VSCode の GitHub Actions 拡張との違い
VSCode には公式の GitHub Actions 拡張 もあり、YAML スキーマや ${{ }} 式の型チェック、アクション・reusable workflow の inputs/outputs 検証までは actionlint と機能が重なります。ただし run: 内のシェルスクリプト解析(shellcheck 連携)やスクリプトインジェクションなどのセキュリティチェック、cron 構文・ランナーラベルの検証はカバーされていません。
pre-commit に組み込むのであれば、actionlint の方が便利です。
Step 2: act でローカル実行する
act は、GitHub Actions のワークフローを Docker 上でローカル実行できる CLI ツールです。
GitHub - nektos/act: Run your GitHub Actions locally 🚀
Run your GitHub Actions locally 🚀. Contribute to nektos/act development by creating an account on GitHub.
push せずにワークフローの動作確認ができます。
インストールと初期設定
Docker が必要です。
1❯ brew install act初回実行時にランナーイメージのサイズを聞かれます。
1❯ act
2? Please choose the default image you want to use with act:
3
4 - Micro: Small runner image, does not contain all tools
5 - Medium: ~500MB, includes most common tools
6 - Large: ~17GB, includes all tools from GitHub Actions runner
7
8Default image? [Medium]:| サイズ | イメージ | 特徴 |
|---|---|---|
| Micro | node:16-buster-slim | 軽量だが最低限のツールのみ |
| Medium | catthehacker/ubuntu:act-latest | バランス型(おすすめ) |
| Large | catthehacker/ubuntu:full-latest | GitHub ランナーに近いが ~17GB と大きい |
選択内容は ~/.actrc に保存されます。
基本的な使い方
1# ワークフローの一覧表示(ドライラン)
2❯ act -l
3Stage Job ID Job name Workflow name Workflow file Events
40 build build Build build.yml pull_request
50 deploy deploy Release release.yml push
6
7# push イベントのワークフローを実行(デフォルト)
8❯ act push
9
10# pull_request イベントを実行
11❯ act pull_request
12
13# workflow_dispatch(手動トリガー)を実行
14❯ act workflow_dispatch
15
16# 特定のジョブだけ実行
17❯ act -j build
18
19# 特定のワークフローファイルを指定
20❯ act -W .github/workflows/build.ymlシークレット・環境変数
1# 値を直接指定
2❯ act -s MY_SECRET=some-value
3
4# セキュア入力(シェル履歴に残らない、おすすめ)
5❯ act -s MY_SECRET
6
7# ファイルから読み込み(dotenv 形式)
8❯ act --secret-file .secrets
9❯ act --env-file .env
10❯ act --var-file .variables # ${{ vars.XXX }} 用.secrets ファイルの例です。
1MY_SECRET=some-value
2ANOTHER_SECRET=another-value便利な機能
.actrc でプロジェクトごとのデフォルト設定
プロジェクトルートに .actrc を作成すると、デフォルト引数を設定できます。
1-P ubuntu-latest=catthehacker/ubuntu:act-latest
2--secret-file .secrets
3--env-file .envイベントペイロードのカスタマイズ
PR 番号やブランチ名などを渡したい場合は JSON ファイルで指定します。
1❯ act pull_request -e event.json1{
2 "pull_request": {
3 "number": 1,
4 "head": {
5 "ref": "feature/my-feature"
6 }
7 }
8}その他のオプション
1❯ act --matrix os:ubuntu-latest # マトリクスの特定の組み合わせだけ実行
2❯ act --action-offline-mode # オフラインで実行
3❯ act --pull=false # イメージの自動プルを無効化制限事項
act は Docker コンテナで実行するため、GitHub ランナーと完全に同一ではありません。そのため、act で通っても GitHub 上で失敗するケース(またはその逆)はありえます。
以下の機能などはサポートされていません。
concurrency,job.permissions,job.timeout-minutes,job.continue-on-errorjob.environment(デプロイ環境のシークレット)GITHUB_STEP_SUMMARY, Problem matchers, Annotations
Unsupported functionality - act - User Guide | Manual | Docs | Documentation
Podman は公式サポート対象外です(Issue #303)。DOCKER_HOST で動く場合もありますが不安定です。
act で Reusable workflow を扱う場合
Reusable workflow 自体を開発する場合
workflow_call を単体で act 実行すると、default のない inputs.xxx が空のまま評価されてしまいます。テスト用の caller ワークフロー(後述の test-reusable.yml)を用意して実行するのが確実です。
1❯ act workflow_dispatch -W .github/workflows/test-reusable.ymlローカル参照(uses: ./...)なら caller と callee を同時に編集しながらテストできます。
ただし、reusable workflow の中では github コンテキストが常に caller のものになるため、actions/checkout で取得されるのは caller のリポジトリです。テストや lint のようにソースコードを対象とする reusable workflow は、caller 側にダミーのソースコードを用意しないと検証できません。
Reusable workflow を呼び出している caller を開発する場合
すでに安定している reusable workflow を呼び出すだけであれば、act が uses: を通常通り解決してくれます。ただしプライベートリポジトリをリモート参照(org/repo/....yml@ref)している場合は、取得するのに認証が必要です。
Step 3: feature ブランチでの開発戦略
ローカルで確認できたら、GitHub 上の本番ランナーで動作確認します。
ここで問題になるのが、トリガーが main への push だけだと feature ブランチで実行できないことです。
まず前提として、push 時に GitHub は push 先ブランチのワークフローファイルを使います。main のファイルではありません。つまり feature ブランチ上で編集して push すれば、その編集版が動きます。ただし branches フィルタに push 先のブランチ名(またはそれにマッチするパターン)が含まれている必要があります。
これを踏まえて、4 つのパターンを紹介します。
パターン1: push トリガーにブランチを一時追加
最もシンプルです。テストが終わったらマージ前に削除します。
1on:
2 push:
3 branches:
4 - main
5 - feature/ci-update # テスト用に一時的に追加パターン2: workflow_dispatch を追加して手動実行
gh CLI や GitHub の Actions タブ(GUI の「Run workflow」ボタン)から、任意のブランチを指定して実行できます。
1on:
2 push:
3 branches: [main]
4 workflow_dispatch: # 追加1❯ gh workflow run build.yml --ref feature/ci-updateただし、ワークフローがデフォルトブランチ(通常は main)に存在していないと手動実行できません(GUI 側も「Run workflow」ボタンごと表示されません)。新規ワークフローの場合はパターン 3 を使います。
パターン3: 空ワークフローを先に main にマージ
新規ワークフロー向けの定番テクニックです。
- 最小限のスケルトン(
workflow_dispatch+ echo だけ)を作成 - PR で
mainにマージ(中身は空なのでリスクなし) - feature ブランチで本実装を開発し、
workflow_dispatchで繰り返しテスト - 実装完了後に PR で本マージ
1# スケルトンの例
2name: Deploy
3on:
4 workflow_dispatch:
5jobs:
6 placeholder:
7 runs-on: ubuntu-latest
8 steps:
9 - run: echo "placeholder"パターン4: pull_request トリガーを使う
ビルド・テスト系ならこれが最も自然です。PR を作れば feature ブランチ上のワークフローが実行されます。
1on:
2 pull_request:
3 branches: [main]どのパターンを使うか
| ワークフローの種類 | おすすめ |
|---|---|
| 既存のビルド・テスト系 | パターン4(pull_request) |
| 既存のデプロイ・リリース系 | パターン2(workflow_dispatch) |
| 新規ワークフロー | パターン3 |
| とにかく素早く試したい | パターン1(ブランチ一時追加) |
feature ブランチで Reusable workflow を扱う場合
Reusable workflow 自体を開発する場合
reusable workflow は workflow_call でしか起動できないため、呼び出し用のテストワークフロー(test-reusable.yml)を用意し、パターン3の要領で空の状態を先に main へマージしておきます。
1# .github/workflows/test-reusable.yml(テスト用)
2name: Test reusable workflow
3on:
4 workflow_dispatch:
5jobs:
6 test:
7 uses: ./.github/workflows/reusable.yml
8 with:
9 some-input: "test-value"ただし act のところで触れた通り、reusable workflow は caller のリポジトリを対象に動きます。テストや lint 系の reusable workflow は、この test caller だけでは検証対象のコードがありません。ダミーのソースコードを用意するか、実際に呼び出している consumer リポジトリ側で uses: を feature ブランチに向けて試すのが良さそうです。
Reusable workflow を呼び出している caller を開発する場合
caller 側の変更が主体なので、パターン1〜4がそのまま使えます。
ひとつ注意が必要なのは、caller と reusable workflow が同一リポジトリにあり、uses: ./... でローカル参照している場合です。ローカル参照では caller と同じコミットのファイルが使われるため、同じ feature ブランチ上で reusable workflow 側にも変更が乗っていると、その変更中のバージョンごと動くことになります。
Step 4: リモートデバッグ
ここまでで大半の問題は解決できますが、それでもダメなときの手段を紹介します。
デバッグログの有効化
リポジトリの Secrets/Variables に以下を true で設定します。
| 変数名 | 用途 |
|---|---|
ACTIONS_RUNNER_DEBUG | ランナーの診断ログ |
ACTIONS_STEP_DEBUG | ステップ実行の詳細ログ |
ワークフロー再実行時に「Enable debug logging」をチェックすることでも一時的に有効化できます。
action-tmate で SSH 接続
action-tmate を使うと、実行中のランナーに SSH で接続してデバッグできます。
GitHub - mxschmitt/action-tmate: Debug your GitHub Actions via SSH by using tmate to get access to the runner system itself.
Debug your GitHub Actions via SSH by using tmate to get access to the runner system itself. - mxschmitt/action-tmate
workflow_dispatch と組み合わせて、必要なときだけセッションを起動する運用がおすすめです。
1on:
2 workflow_dispatch:
3 inputs:
4 debug:
5 description: 'Enable tmate debug session'
6 required: false
7 default: 'false'
8
9jobs:
10 build:
11 runs-on: ubuntu-latest
12 steps:
13 - uses: actions/checkout@v4
14 - name: Setup tmate session
15 if: ${{ github.event.inputs.debug == 'true' }}
16 uses: mxschmitt/action-tmate@v3
17 with:
18 limit-access-to-actor: trueまとめ
GitHub Actions のワークフロー開発フローとして、4 つのステップを紹介しました。
- actionlint で静的解析 → 構文エラーを即座に検出
- act でローカル実行 → push せずに動作確認
- feature ブランチ戦略 → 状況に応じたパターンで GitHub 上で確認
- リモートデバッグ → デバッグログや SSH で原因調査
push → 失敗 → 修正のサイクルは、ここまでの工夫だけでもかなり短くできると思います。
参考
- nektos/act - GitHub
- act 公式ドキュメント
- rhysd/actionlint - GitHub
- actionlint 公式ドキュメント & プレイグラウンド
- vscode-actionlint - VSCode Extension
- GitHub Actions - 公式 VSCode Extension
- GitHub Docs - Events that trigger workflows
- GitHub Docs - Reuse workflows
- GitHub Docs - Reusing workflow configurations
- GitHub Docs - Enabling debug logging
- mxschmitt/action-tmate - GitHub
- Understanding Push Triggers and Branches in GitHub - Ken Muse
- How to test new Github Actions workflows - Josh McArthur
- Support for podman - nektos/act Issue #303




