GitHub Actions の if 条件どおりにステップを実行できない
if が効かないときは、前ステップ失敗時に暗黙で付く success() 条件、文字列 'false' を真と評価する型の取り違え、! で始まる式のクオート漏れを順に疑う。
failure() / always() の明示と式の ${{ }} 囲みで大半は解決する。
公開: 更新:
要約
GitHub Actions の if 条件が効かない原因は大きく 3 つです。
(1) status 関数を含まない if には success() が暗黙で AND されるため、前のステップが失敗すると条件を満たしても実行されない。
(2) ! で始まる式はクオートか ${{ }} で囲まないと YAML として壊れる。
(3) 式の評価では空文字以外の文字列はすべて真なので、'false' という文字列も真になる。
詳細は式の公式ドキュメント(新しいタブで開く)を参照してください。
実行例
失敗するステップの後ろに if の無いステップ A、if: always() の B、if: failure() の C を並べて act で動かすと、A は実行行すら出ないまま飛ばされ、B と C の 2 つだけが走ってジョブは失敗で終わった。
$ act push -W .github/workflows/ifcond.yml
[ifcond/demo] ⭐ Run Main 失敗するステップ
[ifcond/demo] | ここで落とす
[ifcond/demo] ❌ Failure - Main 失敗するステップ [86.5717ms]
[ifcond/demo] ⭐ Run Main if always()
[ifcond/demo] | B: always() なので実行される
[ifcond/demo] ✅ Success - Main if always() [78.2239ms]
[ifcond/demo] ⭐ Run Main if failure()
[ifcond/demo] | C: failure() なので実行される
[ifcond/demo] ✅ Success - Main if failure() [79.9384ms]
[ifcond/demo] 🏁 Job failed— 2026-09-26 時点の出力
検証環境
- 検証日
- 実行環境
local host (Windows 11 Home, Docker 29.8.0)- バージョン
- Node.js 22.14.0
- npm 10.9.2
- Git 2.48.1.windows.1
- Docker 29.8.0
この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。
よくある原因
- 暗黙の success():
if: github.event_name == 'push'のような条件だけを書いた場合、直前までのステップがすべて成功していることが前提条件として追加される。 !のクオート漏れ: YAML では行頭の!がタグ記法と解釈されるため、if: !startsWith(...)はパースに失敗するか意図しない動作になる。- 文字列と真偽値の取り違え:
workflow_dispatchの inputs や outputs 経由の値は文字列で渡ることが多く、if: inputs.dry_runは値が'false'でも真になる。 - job レベル if での env 参照:
envコンテキストはジョブレベルのifでは利用できず、Unrecognized named-value: 'env'のエラーでワークフロー自体が無効になる(ジョブがスキップされるのではない)。 - ref の形式違い: ブランチ判定は
refs/heads/プレフィックス込みで比較する必要がある。
解決策
1. 失敗時にも動かす条件を明示する
steps:
- name: Notify on failure
if: failure()
run: ./notify.sh
- name: Cleanup
if: always()
run: ./cleanup.sh2. 式全体を ${{ }} で囲む
- name: Build (except tags)
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
run: npm run buildクオートで if: "!startsWith(...)" と書いても同じ効果があります。
3. 文字列は明示的に比較する
- name: Deploy
if: ${{ inputs.dry_run == 'false' }}
run: ./deploy.shfromJSON(inputs.dry_run) で真偽値へ変換する方法もあります。
型の扱いはワークフロー構文のリファレンス(新しいタブで開く)に整理されています。