GitHub Actions の実行順序を完全図解:イベント → フィルタ → ジョブ → ステップの流れ

GitHub Actions を使用していて、「なぜこのワークフローが実行されないのだろう?」「どのタイミングでジョブが動くのかわからない」といった疑問を抱えたことはありませんか。GitHub Actions の実行順序は、見た目以上に複雑で奥深いものです。
特に複数のジョブが並行実行される場合や、条件分岐が含まれるワークフローでは、その実行フローを正確に理解することが重要になります。本記事では、GitHub Actions の実行順序を図解を交えて詳しく解説し、皆さんの理解を深めていきます。
図解による理解は、抽象的な概念を具体的にイメージできるため、記憶に残りやすく実践的な知識として身につけることができるでしょう。
背景
GitHub Actions の基本概念
GitHub Actions は、GitHub が提供する CI/CD プラットフォームです。リポジトリ内のコードの変更をトリガーとして、自動的にテスト、ビルド、デプロイなどの処理を実行できます。
GitHub Actions の主要な構成要素について理解しておきましょう。
mermaidflowchart TD
Repository[リポジトリ] -->|contains| Workflows[ワークフロー]
Workflows -->|consists of| Jobs[ジョブ]
Jobs -->|contains| Steps[ステップ]
Steps -->|executes| Actions[アクション]
Repository -->|triggers| Events[イベント]
Events -->|starts| Workflows
GitHub Actions は階層構造で動作しており、最上位のリポジトリから最下位のアクションまで、それぞれが明確な役割を持っています。
ワークフロー実行の全体像
GitHub Actions のワークフローは、特定のイベントが発生した際に起動される一連の自動処理です。この処理は以下の順序で実行されます。
以下の図で、イベント発生からワークフロー完了までの全体的な流れを確認してみましょう。
mermaidflowchart LR
Event[イベント発生] -->|トリガー| Filter{フィルタ条件}
Filter -->|条件一致| Jobs[ジョブ実行]
Filter -->|条件不一致| Skip[スキップ]
Jobs -->|並行/順次| Step1[ステップ1]
Jobs --> Step2[ステップ2]
Jobs --> Step3[ステップ3]
Step1 --> Complete[完了]
Step2 --> Complete
Step3 --> Complete
このフローにおいて重要なのは、各段階で異なる制御ロジックが働いていることです。イベントからフィルタ、ジョブからステップへと、段階的に詳細な制御が行われます。
実行順序が重要な理由
GitHub Actions において実行順序の理解が重要な理由は複数あります。
第一に、依存関係の管理です。例えば、テストが成功した後にのみデプロイを実行したい場合、適切な順序制御が必要になります。
第二に、リソースの効率的な使用です。並行実行できるジョブと順次実行すべきジョブを適切に設計することで、実行時間の短縮とコスト削減が可能です。
第三に、トラブルシューティングの観点です。問題が発生した際に、どの段階で何が起こったかを正確に把握できれば、迅速な問題解決につながります。
課題
複雑な実行フローの理解の難しさ
GitHub Actions のワークフローが複雑になると、その実行順序を把握することが困難になります。特に以下のような状況では、実行フローの理解が困難になりがちです。
以下の図は、複雑なワークフローの一例を示しています。
mermaidflowchart TB
Push[Push Event] --> Test1[Unit Test]
Push --> Test2[Integration Test]
Push --> Lint[Linting]
Test1 --> Build{Build Job}
Test2 --> Build
Lint --> Build
Build -->|success| Deploy1[Deploy to Staging]
Build -->|success| Deploy2[Deploy to Production]
Build -->|failure| Notify[Notify Team]
Deploy1 --> E2E[E2E Testing]
E2E -->|success| Promote[Promote to Production]
E2E -->|failure| Rollback[Rollback]
このような複雑な依存関係を持つワークフローでは、どのジョブがいつ実行されるのか、失敗時にはどのような処理が行われるのかを正確に把握することが困難です。
複数のブランチで異なる条件を設定している場合や、手動トリガーと自動トリガーが混在している場合には、さらに複雑性が増します。
デバッグ時の問題特定の困難さ
ワークフローが期待通りに動作しない場合、問題の原因を特定することは簡単ではありません。
一般的なデバッグの課題として以下があります:
課題 | 説明 | 影響度 |
---|---|---|
ログの分散 | 複数のジョブ・ステップにまたがるログの確認 | 高 |
タイミング問題 | 並行実行による競合状態の発生 | 中 |
環境差異 | ローカル環境と GitHub Actions 環境の違い | 高 |
権限問題 | シークレットやトークンのアクセス権限 | 中 |
特に並行実行されるジョブ間での問題は、実行のたびに異なる結果になる可能性があり、再現性の確保が困難になります。
並行処理と依存関係の混乱
GitHub Actions では、デフォルトでジョブが並行実行されます。これは実行時間の短縮につながる一方で、依存関係の理解を複雑にします。
以下のような混乱が生じやすいです:
- 実行順序の誤解: 並行実行されるジョブの完了順序は保証されない
- 共有リソースへの競合: 同じファイルやサービスに複数のジョブが同時アクセス
- 状態の不整合: あるジョブの結果に依存する処理が、期待したタイミングで実行されない
これらの問題を回避するには、適切な依存関係の設定と、並行実行の制御が必要になります。
解決策
イベント発生の仕組み
GitHub Actions のワークフローは、リポジトリで発生する様々なイベントをトリガーとして起動されます。イベントには手動トリガーと自動トリガーがあり、それぞれ異なる特徴を持っています。
主要なイベントタイプを以下の図で確認しましょう。
mermaidflowchart LR
subgraph "Git Events"
Push[push]
PR[pull_request]
Release[release]
end
subgraph "Schedule Events"
Cron[schedule]
end
subgraph "Manual Events"
Manual[workflow_dispatch]
API[repository_dispatch]
end
Push --> Workflow[ワークフロー実行]
PR --> Workflow
Release --> Workflow
Cron --> Workflow
Manual --> Workflow
API --> Workflow
各イベントタイプの特徴を詳しく見ていきましょう。
Push イベントは、ブランチへのコミットプッシュ時に発生します。最も基本的なトリガーで、コードの変更を検知して CI/CD パイプラインを開始する際に使用されます。
yamlon:
push:
branches: [main, develop]
paths: ['src/**', '!docs/**']
このように、特定のブランチやファイルパスの変更のみをトリガーとするよう設定できます。
Pull Request イベントは、プルリクエストの作成、更新、マージ時に発生します。コードレビュープロセスと連携させる際に重要です。
yamlon:
pull_request:
types: [opened, synchronize, reopened]
branches: [main]
フィルタリング条件の適用
イベントが発生した後、ワークフローが実際に実行されるかはフィルタリング条件によって決定されます。
フィルタリングは複数の層で行われます:
mermaidflowchart TD
Event[イベント発生] --> BranchFilter{ブランチフィルタ}
BranchFilter -->|一致| PathFilter{パスフィルタ}
BranchFilter -->|不一致| Skip1[スキップ]
PathFilter -->|一致| ConditionFilter{条件フィルタ}
PathFilter -->|不一致| Skip2[スキップ]
ConditionFilter -->|一致| Execute[ワークフロー実行]
ConditionFilter -->|不一致| Skip3[スキップ]
ブランチフィルタでは、特定のブランチでのみワークフローを実行するよう制御できます。
yamlon:
push:
branches:
- main
- 'release/**'
branches-ignore:
- 'feature/**'
パスフィルタでは、変更されたファイルのパスに基づいてワークフローの実行を制御します。
yamlon:
push:
paths:
- 'src/**'
- 'package.json'
paths-ignore:
- 'docs/**'
- '**.md'
ジョブ間の依存関係管理
ジョブの依存関係は needs
キーワードを使用して明示的に定義します。これにより、複雑なワークフローでも確実な実行順序を保証できます。
以下は典型的な CI/CD パイプラインの依存関係です:
mermaidflowchart TD
Test[テストジョブ] --> Build[ビルドジョブ]
Lint[リントジョブ] --> Build
Build --> Deploy[デプロイジョブ]
Build --> Security[セキュリティスキャン]
Deploy --> E2E[E2Eテスト]
Security --> E2E
この依存関係を YAML で表現すると以下のようになります:
yamljobs:
test:
runs-on: ubuntu-latest
steps:
- name: Run tests
run: npm test
lint:
runs-on: ubuntu-latest
steps:
- name: Run linter
run: npm run lint
build:
runs-on: ubuntu-latest
needs: [test, lint] # テストとリントが成功した後に実行
steps:
- name: Build application
run: npm run build
依存関係の設定により、並行実行可能なジョブと順次実行が必要なジョブを適切に制御できます。
yamldeploy:
runs-on: ubuntu-latest
needs: build # ビルドジョブの成功が必須
if: github.ref == 'refs/heads/main' # mainブランチのみ
steps:
- name: Deploy to production
run: npm run deploy
ステップの順次実行
ジョブ内のステップは常に順次実行されます。前のステップが成功した場合のみ、次のステップが実行される仕組みです。
mermaidflowchart TD
Step1[Checkout Code] --> Step2[Setup Node.js]
Step2 --> Step3[Install Dependencies]
Step3 --> Step4[Run Tests]
Step4 --> Step5[Build Application]
Step5 --> Step6[Deploy]
Step1 -.->|失敗| End1[ジョブ終了]
Step2 -.->|失敗| End2[ジョブ終了]
Step3 -.->|失敗| End3[ジョブ終了]
Step4 -.->|失敗| End4[ジョブ終了]
Step5 -.->|失敗| End5[ジョブ終了]
ステップレベルでの制御には、条件分岐やエラーハンドリングを組み込むことができます:
yamlsteps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
continue-on-error: true # エラーでも次のステップを実行
- name: Upload test results
if: always() # 前のステップの結果に関わらず実行
uses: actions/upload-artifact@v3
with:
name: test-results
path: test-results.xml
具体例
基本的なワークフロー例
まず、シンプルな Node.js アプリケーションの CI/CD ワークフローを見てみましょう。この例では、テスト、ビルド、デプロイの基本的な流れを図解します。
基本的なワークフローの実行順序は以下のようになります:
mermaidsequenceDiagram
participant Dev as 開発者
participant GitHub as GitHub
participant Runner as GitHub Runner
participant Server as デプロイ先
Dev->>GitHub: git push origin main
GitHub->>Runner: ワークフロー開始
Runner->>Runner: コードをチェックアウト
Runner->>Runner: Node.js環境をセットアップ
Runner->>Runner: 依存関係をインストール
Runner->>Runner: テスト実行
Runner->>Runner: ビルド実行
Runner->>Server: アプリケーションをデプロイ
Runner->>GitHub: 実行結果を報告
このワークフローの YAML 設定は以下のようになります:
yamlname: Basic CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
続いて、環境のセットアップを行います:
yaml- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
依存関係のインストールとテストの実行:
yaml- name: Install dependencies
run: npm ci
- name: Run tests
run: npm run test
- name: Run linting
run: npm run lint
ビルドとデプロイの処理:
yaml- name: Build application
run: npm run build
- name: Deploy to production
if: github.ref == 'refs/heads/main'
run: |
echo "Deploying to production server"
# 実際のデプロイコマンドをここに記述
この基本例では、全てのステップが順次実行され、どれか一つでも失敗すると後続の処理は実行されません。
複雑な依存関係を持つワークフロー例
実際のプロジェクトでは、複数のジョブが並行実行され、複雑な依存関係を持つことが一般的です。以下は、フロントエンドとバックエンドを持つ Web アプリケーションのワークフロー例です。
複雑な依存関係の実行フローを図で確認しましょう:
mermaidflowchart TD
Push[Push Event] --> FE_Test[Frontend Test]
Push --> BE_Test[Backend Test]
Push --> Lint[Linting]
Push --> Security[Security Scan]
FE_Test --> FE_Build[Frontend Build]
BE_Test --> BE_Build[Backend Build]
Lint --> FE_Build
Lint --> BE_Build
FE_Build --> Deploy_Staging[Deploy to Staging]
BE_Build --> Deploy_Staging
Security --> Deploy_Staging
Deploy_Staging --> E2E[E2E Testing]
E2E --> Deploy_Prod[Deploy to Production]
このワークフローでは、テストとリントが並行実行され、全てが成功した後にビルドが実行されます。さらに、ステージング環境での E2E テスト後に本番デプロイが行われます。
フロントエンドのテストジョブ:
yamljobs:
frontend-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci --prefix frontend
- run: npm run test --prefix frontend
バックエンドのテストジョブ:
yamlbackend-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci --prefix backend
- run: npm run test --prefix backend
リントジョブ(全体をチェック):
yamllint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm run lint
依存関係を持つビルドジョブ:
yamlbuild:
runs-on: ubuntu-latest
needs: [frontend-test, backend-test, lint]
steps:
- uses: actions/checkout@v3
- name: Build frontend
run: |
npm ci --prefix frontend
npm run build --prefix frontend
- name: Build backend
run: |
npm ci --prefix backend
npm run build --prefix backend
条件分岐を含むワークフロー例
実際の開発現場では、ブランチやタグに応じて異なる処理を実行することが重要です。以下は、ブランチ戦略と連携した条件分岐の例です。
条件分岐を含むワークフローの実行パターンを図で表現します:
mermaidflowchart TD
Event[Git Event] --> Branch{ブランチ判定}
Branch -->|main| Prod_Flow[本番デプロイフロー]
Branch -->|develop| Stage_Flow[ステージングデプロイフロー]
Branch -->|feature/*| Test_Flow[テストのみフロー]
Branch -->|hotfix/*| Hotfix_Flow[ホットフィックスフロー]
Prod_Flow --> Full_Test[全テスト実行]
Stage_Flow --> Basic_Test[基本テスト実行]
Test_Flow --> Unit_Test[ユニットテストのみ]
Hotfix_Flow --> Quick_Test[クイックテスト]
Full_Test --> Prod_Deploy[本番デプロイ]
Basic_Test --> Stage_Deploy[ステージングデプロイ]
Quick_Test --> Hotfix_Deploy[ホットフィックスデプロイ]
ブランチに応じた条件分岐の実装:
yamlname: Conditional Workflow
on:
push:
branches: [main, develop, 'feature/**', 'hotfix/**']
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm test
本番環境へのデプロイ(main ブランチのみ):
yamldeploy-production:
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Deploy to production
run: |
echo "Deploying to production environment"
# 本番デプロイのコマンド
ステージング環境へのデプロイ(develop ブランチのみ):
yamldeploy-staging:
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/develop'
steps:
- uses: actions/checkout@v3
- name: Deploy to staging
run: |
echo "Deploying to staging environment"
# ステージングデプロイのコマンド
フィーチャーブランチでの軽量テスト:
yamlfeature-test:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/heads/feature/')
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm run test:unit
- run: npm run lint
このような条件分岐を活用することで、ブランチの性質に応じた適切な処理を自動化できます。main ブランチでは厳格なテストと本番デプロイ、feature ブランチでは軽量なテストのみ実行するといった使い分けが可能です。
まとめ
GitHub Actions の実行順序は、イベント → フィルタ → ジョブ → ステップ という明確な階層構造で制御されています。この流れを正確に理解することで、効率的で信頼性の高い CI/CD パイプラインを構築できます。
特に重要なポイントをまとめますと、まずイベントトリガーの適切な設定により、必要なタイミングでのみワークフローを実行することでリソースの無駄遣いを防げます。次に、フィルタリング条件の活用により、変更内容に応じた柔軟な制御が可能になります。
ジョブ間の依存関係管理では、needs
キーワードを使用して明示的な順序制御を行い、ステップの順次実行では条件分岐やエラーハンドリングを組み込むことで、堅牢なワークフローを実現できるでしょう。
図解を活用した理解により、複雑なワークフローの動作も直感的に把握できるようになります。トラブルシューティングの際も、どの段階で問題が発生しているかを素早く特定し、効率的な解決につなげることができるはずです。
皆さんの GitHub Actions 活用の一助となれば幸いです。
関連リンク
- article
GitHub Actions を macOS ランナーで使いこなす:Xcode/コード署名/キーチェーン設定
- article
GitHub Actions 部分実行の比較:paths-filter vs if 条件 vs sparse-checkout
- article
GitHub Actions が突然失敗するときの切り分け術:ログレベル・re-run・debug secrets
- article
GitHub Actions の実行順序を完全図解:イベント → フィルタ → ジョブ → ステップの流れ
- article
GitHub Actions × Node.js:テストとデプロイを自動化する
- article
GitHub Actions で CI/CD パイプラインを構築する方法
- article
Vitest `vi` API 技術チートシート:`mock` / `fn` / `spyOn` / `advanceTimersByTime` 一覧
- article
Pinia ストア分割テンプレ集:domain/ui/session の三層パターン
- article
Obsidian Markdown 拡張チートシート:Callout/埋め込み/内部リンク完全網羅
- article
Micro Frontends 設計:`vite-plugin-federation` で分割可能な UI を構築
- article
TypeScript 公開 API の型設計術:`export type`/`interface`/`class`の責務分担と境界設計
- article
Nuxt nuxi コマンド速見表:プロジェクト作成からモジュール公開まで
- blog
iPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
- blog
Googleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
- blog
【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
- blog
Googleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
- blog
Pixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
- blog
フロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来