ワークフロー構文を理解しよう
ストーリー
「Hello Worldは動いたな。次はワークフローYAMLの構文を体系的に学ぼう」
木村先輩がエディタにワークフローファイルを開いた。
「YAMLの各キーワードには明確な意味がある。
onはいつ実行するか、jobsは何を実行するか、stepsはどう実行するか、runs-onはどこで実行するか。 これらを組み合わせて、思い通りのパイプラインを作れるようになろう」
ワークフローファイルの構造
全体構造
yaml
# ワークフローの名前(GitHub UIに表示される)
name: CI Pipeline
# トリガー条件
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
# 環境変数(ワークフロー全体で使用)
env:
NODE_VERSION: '20'
CI: true
# 権限設定
permissions:
contents: read
pull-requests: write
# ジョブ定義
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run lint
test:
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm teston - トリガー条件
基本的なトリガー
yaml
# 単一のイベント
on: push
# 複数のイベント
on: [push, pull_request]
# 詳細なフィルタ
on:
push:
branches:
- main
- 'release/**' # release/ で始まるブランチ
paths:
- 'src/**' # src/ 以下の変更のみ
- '!src/**/*.md' # Markdownは除外
tags:
- 'v*' # vで始まるタグスケジュール実行
yaml
on:
schedule:
# cron構文: 分 時 日 月 曜日
- cron: '0 9 * * 1-5' # 平日 9:00 UTC に実行
- cron: '0 0 * * 0' # 毎週日曜 0:00 UTC に実行手動実行(workflow_dispatch)
yaml
on:
workflow_dispatch:
inputs:
environment:
description: 'デプロイ先環境'
required: true
default: 'staging'
type: choice
options:
- staging
- production
dry_run:
description: 'ドライラン実行'
required: false
type: boolean
default: falsejobs - ジョブ定義
ジョブの基本構造
yaml
jobs:
# ジョブID(任意の名前)
build:
# ジョブの表示名
name: Build Application
# 実行環境
runs-on: ubuntu-latest
# タイムアウト(分)
timeout-minutes: 15
# ステップ
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run buildジョブ間の依存関係(needs)
yaml
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run lint
test:
needs: lint # lint完了後に実行
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
build:
needs: [lint, test] # lint と test の両方が完了後に実行
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run build
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "Deploying..."ジョブの実行順序
[lint] ← 最初に実行
│
▼
[test] ← lint完了後
│
▼
[build] ← test完了後
│
▼
[deploy] ← build完了後
並列実行
needs を指定しないジョブは並列に実行されます。
yaml
jobs:
lint:
runs-on: ubuntu-latest
steps:
- run: npm run lint
test-unit:
runs-on: ubuntu-latest # lint と並列実行
steps:
- run: npm run test:unit
test-integration:
runs-on: ubuntu-latest # lint、test-unit と並列実行
steps:
- run: npm run test:integration並列実行の図
┌──── [lint] ────┐
│ │
├── [test-unit] ──┤ ← 3つ同時に実行
│ │
└── [test-integ] ─┘
steps - ステップ定義
ステップの詳細オプション
yaml
steps:
# 名前付きステップ
- name: Install dependencies
run: npm ci
# 条件付き実行(if)
- name: Deploy to production
if: github.ref == 'refs/heads/main'
run: npm run deploy
# 失敗しても続行
- name: Optional lint check
continue-on-error: true
run: npm run lint
# 環境変数の設定
- name: Run tests
env:
DATABASE_URL: postgresql://localhost:5432/test
NODE_ENV: test
run: npm test
# 作業ディレクトリの変更
- name: Build frontend
working-directory: ./frontend
run: npm run build
# シェルの指定
- name: PowerShell step
shell: pwsh
run: Write-Host "Hello from PowerShell"ステップの出力(outputs)
あるステップの出力を後続のステップで使う方法です。
yaml
steps:
- name: Get version
id: version
run: |
VERSION=$(cat package.json | jq -r '.version')
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Use version
run: echo "Version is ${{ steps.version.outputs.version }}"環境変数とコンテキスト
環境変数の3つのスコープ
yaml
# ワークフロー全体
env:
APP_NAME: my-app
jobs:
build:
# ジョブレベル
env:
NODE_ENV: production
runs-on: ubuntu-latest
steps:
- name: Build
# ステップレベル
env:
BUILD_TARGET: dist
run: |
echo "App: $APP_NAME"
echo "Env: $NODE_ENV"
echo "Target: $BUILD_TARGET"GitHubコンテキスト
yaml
steps:
- name: Show context
run: |
echo "Repository: ${{ github.repository }}"
echo "Branch: ${{ github.ref_name }}"
echo "SHA: ${{ github.sha }}"
echo "Actor: ${{ github.actor }}"
echo "Event: ${{ github.event_name }}"
echo "Run ID: ${{ github.run_id }}"
echo "Run Number: ${{ github.run_number }}"主要なコンテキスト
| コンテキスト | 説明 | 例 |
|---|---|---|
github | イベント情報 | github.sha, github.ref |
env | 環境変数 | env.NODE_ENV |
secrets | シークレット | secrets.AWS_ACCESS_KEY |
steps | ステップ出力 | steps.build.outputs.version |
jobs | ジョブ出力 | jobs.build.outputs.artifact |
runner | ランナー情報 | runner.os, runner.arch |
条件分岐(if)
よく使う条件式
yaml
jobs:
deploy:
runs-on: ubuntu-latest
# mainブランチへのpushの場合のみ実行
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- run: echo "Deploying..."
notify-failure:
runs-on: ubuntu-latest
# 前のジョブが失敗した場合のみ実行
if: failure()
steps:
- run: echo "Something failed!"
always-run:
runs-on: ubuntu-latest
# 常に実行(失敗しても)
if: always()
steps:
- run: echo "This always runs"条件式のパターン
| 条件 | 構文 |
|---|---|
| mainブランチのみ | if: github.ref == 'refs/heads/main' |
| PRのみ | if: github.event_name == 'pull_request' |
| タグのみ | if: startsWith(github.ref, 'refs/tags/') |
| 前のジョブ成功時 | if: success() |
| 前のジョブ失敗時 | if: failure() |
| 常に実行 | if: always() |
| 特定のアクター | if: github.actor == 'username' |
実践的なワークフロー例
Node.js プロジェクトのCI
yaml
name: Node.js CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
NODE_VERSION: '20'
permissions:
contents: read
jobs:
lint:
name: Code Quality
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint
- name: Check types
run: npm run typecheck
test:
name: Tests
needs: lint
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test -- --coverage
- name: Upload coverage
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
build:
name: Build
needs: test
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: build
path: dist/まとめ
| ポイント | 内容 |
|---|---|
on | トリガー条件(push, PR, schedule, workflow_dispatch) |
jobs | ジョブ定義、needs で依存関係を指定 |
steps | uses でAction、run でコマンド、if で条件分岐 |
| コンテキスト | github.*, secrets.*, steps.* 等で動的な値を参照 |
チェックリスト
- ワークフローYAMLの全体構造を把握した
-
onでのトリガー条件の指定方法を理解した -
needsによるジョブ間の依存関係を設定できる - 環境変数とコンテキストの使い方を理解した
-
ifによる条件分岐のパターンを把握した
次のステップへ
次のセクションでは、トリガーとイベントについてさらに深掘りします。 プッシュ、PR、スケジュールなど、さまざまなイベントの活用方法を学びましょう。
推定読了時間: 40分