GitHub Actionsの開発フローを考えてみた

2026.07.26
2026.07.26
CI/CD

はじめに

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

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 🚀

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]:
サイズイメージ特徴
Micronode:16-buster-slim軽量だが最低限のツールのみ
Mediumcatthehacker/ubuntu:act-latestバランス型(おすすめ)
Largecatthehacker/ubuntu:full-latestGitHub ランナーに近いが ~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.json
event.json
1{
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-error
  • job.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 にマージ

新規ワークフロー向けの定番テクニックです。

  1. 最小限のスケルトン(workflow_dispatch + echo だけ)を作成
  2. PR で main にマージ(中身は空なのでリスクなし)
  3. feature ブランチで本実装を開発し、workflow_dispatch で繰り返しテスト
  4. 実装完了後に 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.

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 つのステップを紹介しました。

  1. actionlint で静的解析 → 構文エラーを即座に検出
  2. act でローカル実行 → push せずに動作確認
  3. feature ブランチ戦略 → 状況に応じたパターンで GitHub 上で確認
  4. リモートデバッグ → デバッグログや SSH で原因調査

push → 失敗 → 修正のサイクルは、ここまでの工夫だけでもかなり短くできると思います。

参考

Support

\ この記事が役に立ったと思ったら、サポートお願いします! /

buy me a coffee
Share

Profile

author

Masa

都内のIT企業で働くエンジニア
自分が学んだことをブログでわかりやすく発信していきながらスキルアップを目指していきます!

buy me a coffee