GitHub Actions を workflow_dispatch で切り分ける
はじめに
GitHub Actions で複雑なワークフローを管理していると、単一のワークフローファイルが肥大化し、保守性が悪化することがあります。
そこで workflow_dispatch
を使用した設計を導入することで保守性を向上を試みた話です。
workflow_dispatch とは
workflow_dispatch
は GitHub Actions のトリガーの一つであり、手動実行やAPI経由でワークフローを起動できる機能です。
さらに、他のワークフローから workflow_call
イベントと組み合わせることで、再利用可能なワークフローを作成できます。
これが基本的な機能です。
name: Deploy Application
on:
workflow_dispatch:
inputs:
environment:
description: 'Target environment'
required: true
type: choice
options: ['staging', 'production']
workflow_call:
inputs:
environment:
required: true
type: string
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy to ${{ inputs.environment }}
run: echo "Deploying to ${{ inputs.environment }}"
呼び出される側のワークフロー(.github/workflows/deploy.yml)の例
name: Main Workflow
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: echo "Running tests"
deploy-staging:
needs: test
uses: ./.github/workflows/deploy.yml
with:
environment: staging
# 呼び出す側のワークフロー(.github/workflows/main.yml)
GitHub API を使った別リポジトリからの呼び出し
workflow_dispatch
は同一リポジトリ内だけでなく、GitHub API を使用することで外部リポジトリからも呼び出すことができます。
これにより、マイクロサービス間の連携や、共通ワークフローの中央管理が可能になります。
// Octokit.js
// https://github.com/octokit/core.js#readme
const octokit = new Octokit({
auth: 'YOUR-TOKEN'
})
await octokit.request('POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches', {
owner: 'OWNER',
repo: 'REPO',
workflow_id: 'WORKFLOW_ID',
ref: 'topic-branch',
inputs: {
name: 'Mona the Octocat',
home: 'San Francisco, CA'
},
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
})
メリット
workflow_dispatch
自体のメリットやAPI化することで得られるメリット
責任の分離とモジュール化
各ワークフローが単一の責任を持つことで、コードの理解と保守が容易になります。
従来の課題感
- 1つのワークフローに複数の処理が混在
- 特定の処理だけを修正したい場合でも全体への影響を考慮する必要
改善後
- テスト、ビルド、デプロイなど、処理ごとにワークフローを分離
- 独立した単位でのテストと修正が可能
再利用性の向上
共通の処理を別ワークフローに切り出すことで、複数の場所から呼び出せます。
※ GitHub API を利用することで別 Repository からでも呼び出し可能
活用例
- 複数の環境(staging/production)への同一デプロイ処理
- 異なるブランチでの共通テストスイート
- 品質チェックの標準化
並列実行の最適化
独立したワークフローは並列実行が可能で、全体の実行時間を短縮できます。
つまり非同期で実行されます。
jobs:
call-test:
uses: ./.github/workflows/test.yml
call-security-scan:
uses: ./.github/workflows/security.yml
call-lint:
uses: ./.github/workflows/lint.yml
deploy:
needs: [call-test, call-security-scan, call-lint]
uses: ./.github/workflows/deploy.yml
デバッグとトラブルシューティング
問題が発生した際に、関連する処理だけを個別に実行してデバッグが容易です。
-
workflow_dispatch
により手動で特定のワークフローを実行 - 問題の範囲を絞り込んで効率的な調査が可能
- 本番環境での緊急時対応が迅速化
セキュリティの向上
機密性の高い処理を分離し、必要な権限のみを付与できます。
# デプロイワークフロー - 本番環境へのアクセス権限のみ
name: Production Deploy
on:
workflow_dispatch:
permissions:
contents: read
id-token: write # AWS認証用
# テストワークフロー - 最小権限
name: Test Suite
on:
workflow_dispatch:
permissions:
contents: read
環境固有の設定管理
環境ごとに異なるワークフローを作成し、適切な設定を適用できます。
# 本番用デプロイワークフロー
environment: production
secrets:
- PROD_API_KEY
- PROD_DATABASE_URL
# 開発用デプロイワークフロー
environment: development
secrets:
- DEV_API_KEY
- DEV_DATABASE_URL
セキュリティ考慮事項
トークン管理
name: Trigger External Workflow
on:
workflow_dispatch:
jobs:
trigger:
runs-on: ubuntu-latest
steps:
- name: Trigger external workflow
env:
GITHUB_TOKEN: ${{ secrets.CROSS_REPO_TOKEN }}
run: |
gh api repos/target-org/target-repo/dispatches \
--method POST \
--field event_type='deploy' \
--field 'client_payload[environment]=production'
GitHub Secrets での安全なトークン管理
IATによる管理
GitHub App で IAT を生成し 一時的なトークンの利用を検討
権限の最小化
- Fine-grained personal access token の推奨スコープ
- Actions: write (ワークフロー実行用)
- Contents: read (リポジトリ読み取り用)
- Metadata: read (基本情報読み取り用)
まとめ
workflow_dispatch
を活用したワークフローの切り分けは、以下の場面で特に効果的だと考えています。
- 複雑なCI/CDパイプラインの管理
- 複数環境への展開プロセス
- 共通処理の標準化
- チーム間での作業分担
- マイクロサービス間の連携
- 組織横断的なワークフロー管理
- 外部システムからのデプロイ制御
GitHub API を活用することで、単一リポジトリの枠を超えた柔軟なCI/CDシステムを構築でき、保守性・再利用性・可読性の向上により開発生産性が大幅に改善されます。
実際に運用してみた所感として、単一責任の原則で切り分けることで保守は容易になりましたが、workflow_dispatch
を利用する際の認証周りで GitHub App の ID 管理などが複雑になるため、適切なモデリングが必要だと感じています。
この点は今後の改善余地があります。
Discussion