GitHub Actions
CI/CDツール
GitHub Actions
概要
GitHub Actionsは、GitHubネイティブのCI/CDプラットフォームです。YAML設定によるワークフロー定義、豊富なマーケットプレイス、GitHub統合により、開発からデプロイまでの自動化を実現します。
詳細
GitHub Actions(ギットハブ アクション)は、Microsoftが提供するGitHubプラットフォーム統合型のCI/CD(継続的インテグレーション・継続的デリバリー)サービスです。2019年にリリースされて以来、ソフトウェア開発ライフサイクルの自動化において中心的な役割を果たしています。リポジトリに.github/workflows/ディレクトリ内のYAMLファイルでワークフローを定義することで、コードのビルド、テスト、デプロイを自動化できます。GitHub Marketplaceでは11,000以上の再利用可能なアクションが提供されており、Node.js、Python、Java、.NETなど幅広い言語とフレームワークをサポートします。Linux、macOS、Windows、ARM、GPUランナーを提供し、マトリックスビルドや並列実行により効率的なCI/CDパイプラインを構築可能です。セルフホストランナーにも対応し、企業環境での柔軟な運用を実現します。2024年以降はセキュリティ機能が強化され、Artifact Attestations、暗号化シークレット、依存関係スキャンにより安全な開発プロセスを提供しています。
メリット・デメリット
メリット
- GitHubとの完全統合: リポジトリ、Issues、Pull Requestとシームレス連携
- 豊富なマーケットプレイス: 11,000以上の再利用可能なアクション
- 多様な実行環境: Linux、macOS、Windows、ARM、GPUランナー対応
- 無料利用枠: パブリックリポジトリは無制限、プライベートでも月2,000分
- スケーラビリティ: マトリックスビルドと並列実行による高速処理
- セキュリティ: 暗号化シークレット、Artifact Attestations対応
- 柔軟性: セルフホストランナーとカスタムアクション作成
- 設定の版管理: YAMLファイルでワークフロー設定をバージョン管理
デメリット
- GitHubロックイン: GitHub以外のプラットフォームでは使用不可
- 料金: プライベートリポジトリでの大規模利用は高コスト
- 学習コスト: YAML記法とワークフロー概念の理解が必要
- デバッグの複雑さ: ワークフロー失敗時の原因特定が困難
- 実行時間制限: ジョブあたり最大6時間の制限
- ストレージ制限: アーティファクトとキャッシュの保存期間制限
- ネットワーク制約: 外部APIアクセスの制限やレート制限
主要リンク
- GitHub Actions公式サイト
- GitHub Actions公式ドキュメント
- GitHub Marketplace
- GitHub Actions Starter Workflows
- GitHub Actions Runner
- GitHub Skills
書き方の例
基本的なNode.jsワークフロー
# .github/workflows/node.yml
name: Node.js CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x, 22.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run build --if-present
- run: npm test
TypeScriptプロジェクトのCI/CD
# .github/workflows/typescript.yml
name: TypeScript CI/CD
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
NODE_VERSION: '20.x'
jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
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: Type check
run: npm run type-check
- name: Lint
run: npm run lint
- name: Run tests
run: npm run test:coverage
- name: Upload coverage reports
uses: codecov/codecov-action@v3
with:
file: ./coverage/lcov.info
build:
needs: lint-and-test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-files
path: dist/
retention-days: 30
Docker イメージビルドとデプロイ
# .github/workflows/docker.yml
name: Docker Build and Deploy
on:
push:
branches: [main]
tags: ['v*']
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
deploy:
needs: build-and-push
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to production
uses: appleboy/[email protected]
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main
docker stop myapp || true
docker rm myapp || true
docker run -d --name myapp -p 80:3000 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main
マルチプラットフォーム対応
# .github/workflows/multi-platform.yml
name: Multi-Platform CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.9', '3.10', '3.11', '3.12']
exclude:
- os: macos-latest
python-version: '3.9'
- os: windows-latest
python-version: '3.12'
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest
- name: Run tests
run: pytest tests/ -v
- name: Platform-specific commands
shell: bash
run: |
if [[ "${{ matrix.os }}" == "ubuntu-latest" ]]; then
echo "Running Ubuntu-specific commands"
sudo apt-get update
elif [[ "${{ matrix.os }}" == "windows-latest" ]]; then
echo "Running Windows-specific commands"
choco --version
elif [[ "${{ matrix.os }}" == "macos-latest" ]]; then
echo "Running macOS-specific commands"
brew --version
fi
条件付きワークフローとリリース自動化
# .github/workflows/release.yml
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Run tests
run: npm test
- name: Generate changelog
id: changelog
run: |
# Generate changelog from git commits
echo "CHANGELOG<<EOF" >> $GITHUB_OUTPUT
git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:"- %s (%h)" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Create GitHub Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref_name }}
release_name: Release ${{ github.ref_name }}
body: |
## Changes in this release
${{ steps.changelog.outputs.CHANGELOG }}
draft: false
prerelease: ${{ contains(github.ref_name, 'beta') || contains(github.ref_name, 'alpha') }}
- name: Publish to NPM
if: ${{ !contains(github.ref_name, 'beta') && !contains(github.ref_name, 'alpha') }}
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
セキュリティスキャンとコード品質
# .github/workflows/security.yml
name: Security and Quality
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 0 * * 1' # 毎週月曜日
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run dependency vulnerability scan
uses: actions/dependency-review-action@v3
if: github.event_name == 'pull_request'
- name: Run CodeQL Analysis
uses: github/codeql-action/init@v2
with:
languages: javascript
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@v2
if: always()
with:
sarif_file: 'trivy-results.sarif'