github-research-tool/features/05-github-actions.md
marketing-shibata50 59b60ace06 feat: add comprehensive GitHub guides expansion
🆕 New Guides Added:
- GitHub Actions complete guide (CI/CD automation)
- GitHub Security comprehensive guide (enterprise security)
- GitHub Pages detailed guide (website publishing)

🔗 Navigation Improvements:
- Updated index.md with all 7 guides
- Added cross-navigation between all guides
- Enhanced learning paths for different user types
- Comprehensive learning flow diagrams

📚 Content Highlights:
- Jenkins/CircleCI migration strategies
- Enterprise security best practices
- WordPress to GitHub Pages migration
- Advanced automation workflows
- Complete external tool replacements

🎯 User Experience:
- Role-based learning recommendations
- Consistent navigation structure
- Progressive learning paths
- Cross-reference linking

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-20 13:22:23 +09:00

45 KiB
Raw Permalink Blame History

layout title description
default GitHub Actions完全ガイド Jenkins・CircleCI代替のCI/CD自動化とGitHub Actions完全活用法

GitHub Actions - 完全なCI/CD自動化

GitHub Actionsを活用して、Jenkins・CircleCI・GitLab CI・Azure DevOpsなどの外部CI/CDツールに依存しない、統合された自動化環境を構築する完全ガイド。コードのビルド・テスト・デプロイから、複雑なワークフロー自動化まで網羅します。

🎯 学習目標

  • GitHub Actions の全機能理解と実践的活用
  • 外部CI/CDツールからの完全移行戦略
  • セキュアで効率的なワークフロー設計
  • 高度な自動化とDevOps実践
  • コスト最適化と運用効率向上

📚 目次

  1. GitHub Actions 基本概念
  2. CI/CDパイプライン構築
  3. 高度なワークフロー設計
  4. セキュリティ・シークレット管理
  5. 外部ツールからの移行
  6. 運用最適化・監視

1. GitHub Actions 基本概念

🏗️ アーキテクチャ理解

核心コンポーネント

# GitHub Actions の基本構造
Workflow (ワークフロー)
├── Events (イベント) - トリガー条件
├── Jobs (ジョブ) - 実行単位
│   ├── Steps (ステップ) - 個別タスク
│   │   ├── Actions (アクション) - 再利用可能な処理
│   │   └── Commands (コマンド) - シェル実行
│   └── Runner (ランナー) - 実行環境
├── Secrets (シークレット) - 機密情報
└── Environment (環境) - デプロイメント設定

基本ワークフロー例

# .github/workflows/basic-ci.yml
name: Basic CI Pipeline

# イベント定義
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 2 * * 1'  # 毎週月曜 2時

# グローバル環境変数
env:
  NODE_VERSION: '18'
  CACHE_KEY: node-modules

jobs:
  # ジョブ1: コード品質チェック
  quality-check:
    name: Code Quality
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Lint check
        run: npm run lint
      
      - name: Type check
        run: npm run type-check
      
      - name: Security audit
        run: npm audit --audit-level high

  # ジョブ2: テスト実行
  test:
    name: Test Suite
    runs-on: ubuntu-latest
    needs: quality-check
    
    strategy:
      matrix:
        node-version: [16, 18, 20]
        os: [ubuntu-latest, windows-latest, macos-latest]
        
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run tests
        run: npm run test:coverage
        env:
          CI: true
      
      - name: Upload coverage
        uses: codecov/codecov-action@v3
        if: matrix.node-version == 18 && matrix.os == 'ubuntu-latest'
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

🎛️ イベントトリガーの活用

包括的なトリガー設定

# 高度なイベント設定例
on:
  # プッシュイベント
  push:
    branches: 
      - main
      - 'release/**'
      - 'hotfix/**'
    paths:
      - 'src/**'
      - 'package.json'
      - '.github/workflows/**'
    tags:
      - 'v*'
  
  # プルリクエストイベント
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
    branches: [main, develop]
    paths-ignore:
      - 'docs/**'
      - '*.md'
  
  # Issue イベント
  issues:
    types: [opened, labeled, assigned]
  
  # リリースイベント
  release:
    types: [published, prereleased]
  
  # スケジュール実行
  schedule:
    - cron: '0 2 * * 1-5'    # 平日 2時
    - cron: '0 10 * * 6'     # 土曜 10時
  
  # 手動実行
  workflow_dispatch:
    inputs:
      environment:
        description: 'Deployment environment'
        required: true
        default: 'staging'
        type: choice
        options:
          - staging
          - production
      debug:
        description: 'Enable debug logging'
        required: false
        default: false
        type: boolean
      version:
        description: 'Version to deploy'
        required: false
        type: string

  # 他のワークフローからの呼び出し
  workflow_call:
    inputs:
      config-path:
        required: true
        type: string
    secrets:
      api-key:
        required: true

2. CI/CDパイプライン構築

🔄 フルスタックCI/CDパイプライン

Node.js アプリケーション用

# .github/workflows/nodejs-cicd.yml
name: Node.js CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  # ステージ1: ビルド・テスト
  build-and-test:
    name: Build and Test
    runs-on: ubuntu-latest
    
    outputs:
      version: ${{ steps.version.outputs.version }}
      image-digest: ${{ steps.build.outputs.digest }}
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'
      
      - name: Generate version
        id: version
        run: |
          if [[ $GITHUB_REF == refs/tags/* ]]; then
            VERSION=${GITHUB_REF#refs/tags/}
          else
            VERSION=$(git describe --tags --always --dirty)
          fi
          echo "version=$VERSION" >> $GITHUB_OUTPUT
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run linting
        run: npm run lint
      
      - name: Run type checking
        run: npm run type-check
      
      - name: Run unit tests
        run: npm run test:unit -- --coverage
      
      - name: Run integration tests
        run: npm run test:integration
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
      
      - name: Build application
        run: npm run build
        env:
          NODE_ENV: production
          VERSION: ${{ steps.version.outputs.version }}
      
      - name: Upload build artifacts
        uses: actions/upload-artifact@v3
        with:
          name: build-artifacts
          path: |
            dist/
            package.json
            package-lock.json
          retention-days: 7

  # ステージ2: セキュリティスキャン
  security-scan:
    name: Security Scanning
    runs-on: ubuntu-latest
    needs: build-and-test
    
    permissions:
      security-events: write
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-artifacts
      
      - 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 results
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: 'trivy-results.sarif'
      
      - name: OWASP Dependency Check
        uses: dependency-check/Dependency-Check_Action@main
        with:
          project: 'my-project'
          path: '.'
          format: 'SARIF'
          args: >
            --enableRetired
            --enableExperimental
            --failOnCVSS 7

  # ステージ3: E2Eテスト
  e2e-tests:
    name: E2E Tests
    runs-on: ubuntu-latest
    needs: build-and-test
    
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: testdb
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
      
      redis:
        image: redis:7
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 6379:6379
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-artifacts
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Setup test database
        run: |
          npm run db:migrate
          npm run db:seed
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
      
      - name: Install Playwright
        run: npx playwright install --with-deps
      
      - name: Start application
        run: |
          npm start &
          npx wait-on http://localhost:3000 --timeout 60000
        env:
          NODE_ENV: test
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
          REDIS_URL: redis://localhost:6379
      
      - name: Run E2E tests
        run: npm run test:e2e
        env:
          BASE_URL: http://localhost:3000
      
      - name: Upload test results
        uses: actions/upload-artifact@v3
        if: failure()
        with:
          name: e2e-results
          path: |
            test-results/
            playwright-report/

  # ステージ4: Dockerイメージビルド
  build-image:
    name: Build Docker Image
    runs-on: ubuntu-latest
    needs: [build-and-test, security-scan]
    if: github.event_name == 'push'
    
    permissions:
      contents: read
      packages: write
    
    outputs:
      image: ${{ steps.image.outputs.image }}
      digest: ${{ steps.build.outputs.digest }}
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      
      - name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-artifacts
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      
      - 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}}
            type=sha,prefix={{branch}}-
      
      - name: Build and push image
        id: build
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          build-args: |
            VERSION=${{ needs.build-and-test.outputs.version }}
      
      - name: Output image
        id: image
        run: echo "image=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build-and-test.outputs.version }}" >> $GITHUB_OUTPUT

  # ステージ5: ステージング環境デプロイ
  deploy-staging:
    name: Deploy to Staging
    runs-on: ubuntu-latest
    needs: [build-image, e2e-tests]
    if: github.ref == 'refs/heads/develop'
    
    environment:
      name: staging
      url: https://staging.example.com
    
    steps:
      - name: Deploy to staging
        uses: azure/webapps-deploy@v2
        with:
          app-name: 'my-app-staging'
          publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE_STAGING }}
          images: ${{ needs.build-image.outputs.image }}
      
      - name: Run smoke tests
        run: |
          curl -f https://staging.example.com/health || exit 1
          curl -f https://staging.example.com/api/status || exit 1

  # ステージ6: 本番環境デプロイ
  deploy-production:
    name: Deploy to Production
    runs-on: ubuntu-latest
    needs: [build-image, deploy-staging]
    if: github.ref == 'refs/heads/main'
    
    environment:
      name: production
      url: https://example.com
    
    steps:
      - name: Deploy to production
        uses: azure/webapps-deploy@v2
        with:
          app-name: 'my-app-production'
          publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE_PRODUCTION }}
          images: ${{ needs.build-image.outputs.image }}
      
      - name: Run production smoke tests
        run: |
          curl -f https://example.com/health || exit 1
          curl -f https://example.com/api/status || exit 1
      
      - name: Notify deployment
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          channel: '#deployments'
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}
        if: always()

🐍 Python アプリケーション用

# .github/workflows/python-cicd.yml
name: Python CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    name: Test Suite
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        python-version: ['3.8', '3.9', '3.10', '3.11']
    
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: testdb
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
      
      - name: Cache dependencies
        uses: actions/cache@v3
        with:
          path: ~/.cache/pip
          key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
          restore-keys: |
            ${{ runner.os }}-pip-
      
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install -r requirements-dev.txt
      
      - name: Lint with flake8
        run: |
          flake8 src/ tests/ --count --select=E9,F63,F7,F82 --show-source --statistics
          flake8 src/ tests/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
      
      - name: Type check with mypy
        run: mypy src/
      
      - name: Test with pytest
        run: |
          pytest tests/ --cov=src/ --cov-report=xml --cov-report=html
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
      
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage.xml
          flags: unittests
          name: codecov-umbrella

  security:
    name: Security Scan
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install safety bandit
      
      - name: Run safety check
        run: safety check
      
      - name: Run bandit security check
        run: bandit -r src/ -f json -o bandit-report.json
      
      - name: Upload security scan results
        uses: actions/upload-artifact@v3
        if: failure()
        with:
          name: security-reports
          path: bandit-report.json

  build-and-deploy:
    name: Build and Deploy
    runs-on: ubuntu-latest
    needs: [test, security]
    if: github.ref == 'refs/heads/main'
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      
      - name: Build package
        run: |
          python -m pip install --upgrade pip build
          python -m build
      
      - name: Deploy to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          password: ${{ secrets.PYPI_API_TOKEN }}

3. 高度なワークフロー設計

🔄 再利用可能ワークフロー

共通CI/CDテンプレート

# .github/workflows/reusable-ci.yml
name: Reusable CI Workflow

on:
  workflow_call:
    inputs:
      node-version:
        required: false
        type: string
        default: '18'
      environment:
        required: false
        type: string
        default: 'development'
      run-e2e:
        required: false
        type: boolean
        default: false
    secrets:
      NPM_TOKEN:
        required: false
      CODECOV_TOKEN:
        required: false
    outputs:
      build-version:
        description: "Built application version"
        value: ${{ jobs.build.outputs.version }}
      artifact-name:
        description: "Build artifact name"
        value: ${{ jobs.build.outputs.artifact-name }}

jobs:
  build:
    name: Build and Test
    runs-on: ubuntu-latest
    
    outputs:
      version: ${{ steps.version.outputs.version }}
      artifact-name: ${{ steps.artifact.outputs.name }}
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
          cache: 'npm'
          registry-url: 'https://registry.npmjs.org'
      
      - name: Generate version
        id: version
        run: |
          VERSION=$(date +%Y%m%d)-$(git rev-parse --short HEAD)
          echo "version=$VERSION" >> $GITHUB_OUTPUT
      
      - name: Install dependencies
        run: npm ci
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
      
      - name: Run tests
        run: npm run test:coverage
      
      - name: Upload coverage
        if: secrets.CODECOV_TOKEN != ''
        uses: codecov/codecov-action@v3
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
      
      - name: Build application
        run: npm run build
        env:
          NODE_ENV: ${{ inputs.environment }}
          VERSION: ${{ steps.version.outputs.version }}
      
      - name: Create artifact
        id: artifact
        run: |
          ARTIFACT_NAME="build-${{ steps.version.outputs.version }}"
          echo "name=$ARTIFACT_NAME" >> $GITHUB_OUTPUT
      
      - name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: ${{ steps.artifact.outputs.name }}
          path: dist/

  e2e-tests:
    name: E2E Tests
    runs-on: ubuntu-latest
    needs: build
    if: inputs.run-e2e
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: ${{ needs.build.outputs.artifact-name }}
          path: dist/
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Install Playwright
        run: npx playwright install --with-deps
      
      - name: Run E2E tests
        run: npm run test:e2e

ワークフローの呼び出し

# .github/workflows/main-ci.yml
name: Main CI Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  ci:
    name: Continuous Integration
    uses: ./.github/workflows/reusable-ci.yml
    with:
      node-version: '18'
      environment: 'production'
      run-e2e: true
    secrets:
      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
  
  deploy:
    name: Deploy Application
    runs-on: ubuntu-latest
    needs: ci
    if: github.ref == 'refs/heads/main'
    
    steps:
      - name: Download build artifacts
        uses: actions/download-artifact@v3
        with:
          name: ${{ needs.ci.outputs.artifact-name }}
      
      - name: Deploy to production
        run: |
          echo "Deploying version ${{ needs.ci.outputs.build-version }}"
          # デプロイメントロジック

🎯 コンポジットアクション

カスタムアクション作成

# .github/actions/setup-app/action.yml
name: 'Setup Application'
description: 'Setup Node.js application with caching and dependencies'

inputs:
  node-version:
    description: 'Node.js version to use'
    required: false
    default: '18'
  cache-dependency-path:
    description: 'Path to dependency file'
    required: false
    default: 'package-lock.json'
  install-command:
    description: 'Command to install dependencies'
    required: false
    default: 'npm ci'

outputs:
  cache-hit:
    description: 'Cache hit status'
    value: ${{ steps.cache.outputs.cache-hit }}
  node-version:
    description: 'Installed Node.js version'
    value: ${{ steps.setup-node.outputs.node-version }}

runs:
  using: 'composite'
  steps:
    - name: Setup Node.js
      id: setup-node
      uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
        cache: 'npm'
        cache-dependency-path: ${{ inputs.cache-dependency-path }}
    
    - name: Cache node modules
      id: cache
      uses: actions/cache@v3
      with:
        path: ~/.npm
        key: ${{ runner.os }}-node-${{ hashFiles(inputs.cache-dependency-path) }}
        restore-keys: |
          ${{ runner.os }}-node-
    
    - name: Install dependencies
      shell: bash
      run: ${{ inputs.install-command }}
      env:
        NODE_AUTH_TOKEN: ${{ env.NODE_AUTH_TOKEN }}
    
    - name: Verify installation
      shell: bash
      run: |
        echo "Node.js version: $(node --version)"
        echo "npm version: $(npm --version)"
        echo "Dependencies installed successfully"

アクションの使用

# ワークフローでの使用例
steps:
  - uses: actions/checkout@v4
  
  - name: Setup application
    uses: ./.github/actions/setup-app
    with:
      node-version: '18'
      install-command: 'npm ci --production'
  
  - name: Build application
    run: npm run build

4. セキュリティ・シークレット管理

🔐 シークレット管理戦略

環境別シークレット設定

# セキュリティベストプラクティス
name: Secure Deployment

on:
  push:
    branches: [main]

jobs:
  deploy:
    name: Secure Deployment
    runs-on: ubuntu-latest
    
    # 環境の設定
    environment:
      name: production
      url: https://example.com
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ vars.AWS_REGION }}
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          role-session-name: GitHubActions
      
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2
      
      - name: Build and push Docker image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: ${{ vars.ECR_REPOSITORY }}
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
      
      - name: Deploy to ECS
        run: |
          aws ecs update-service \
            --cluster ${{ vars.ECS_CLUSTER }} \
            --service ${{ vars.ECS_SERVICE }} \
            --force-new-deployment

OIDC プロバイダー認証

# クラウドプロバイダーとのOIDC認証
name: OIDC Authentication

on:
  push:
    branches: [main]

permissions:
  id-token: write   # OIDC トークン取得に必要
  contents: read

jobs:
  deploy-aws:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
          role-session-name: GitHubActions
          aws-region: us-east-1
      
      - name: Deploy to AWS
        run: |
          aws s3 sync ./dist s3://${{ vars.S3_BUCKET }}/

  deploy-azure:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Azure Login
        uses: azure/login@v1
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      
      - name: Deploy to Azure
        run: |
          az webapp deployment source config-zip \
            --resource-group ${{ vars.AZURE_RESOURCE_GROUP }} \
            --name ${{ vars.AZURE_APP_NAME }} \
            --src ./dist.zip

🛡️ セキュリティスキャン自動化

包括的セキュリティチェック

# .github/workflows/security-scan.yml
name: Security Scanning

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 3 * * 1'  # 毎週月曜 3時

permissions:
  security-events: write
  contents: read

jobs:
  code-scanning:
    name: Code Scanning
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        language: ['javascript', 'python']
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Initialize CodeQL
        uses: github/codeql-action/init@v2
        with:
          languages: ${{ matrix.language }}
          queries: security-extended,security-and-quality
      
      - name: Autobuild
        uses: github/codeql-action/autobuild@v2
      
      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v2
        with:
          category: "/language:${{matrix.language}}"

  dependency-scanning:
    name: Dependency Scanning
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - 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
        with:
          sarif_file: 'trivy-results.sarif'
      
      - name: Snyk security scan
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high --sarif-file-output=snyk.sarif
      
      - name: Upload Snyk results
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: snyk.sarif

  container-scanning:
    name: Container Scanning
    runs-on: ubuntu-latest
    if: github.event_name == 'push'
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Build Docker image
        run: docker build -t test-image .
      
      - name: Run Trivy container scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'test-image'
          format: 'sarif'
          output: 'trivy-container.sarif'
      
      - name: Upload container scan results
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: 'trivy-container.sarif'

  secret-scanning:
    name: Secret Scanning
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - name: TruffleHog OSS
        uses: trufflesecurity/trufflehog@main
        with:
          path: ./
          base: main
          head: HEAD
          extra_args: --debug --only-verified

5. 外部ツールからの移行

🔄 Jenkins からの移行

Jenkinsfile → GitHub Actions 変換例

// 元のJenkinsfile
pipeline {
    agent any
    
    environment {
        NODE_VERSION = '18'
        DOCKER_REGISTRY = 'myregistry.com'
    }
    
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        
        stage('Build') {
            steps {
                sh 'npm ci'
                sh 'npm run build'
            }
        }
        
        stage('Test') {
            parallel {
                stage('Unit Tests') {
                    steps {
                        sh 'npm run test:unit'
                    }
                    post {
                        always {
                            publishTestResults testResultsPattern: 'test-results.xml'
                        }
                    }
                }
                
                stage('E2E Tests') {
                    steps {
                        sh 'npm run test:e2e'
                    }
                }
            }
        }
        
        stage('Deploy') {
            when {
                branch 'main'
            }
            steps {
                sh 'docker build -t $DOCKER_REGISTRY/myapp:$BUILD_NUMBER .'
                sh 'docker push $DOCKER_REGISTRY/myapp:$BUILD_NUMBER'
            }
        }
    }
    
    post {
        always {
            cleanWs()
        }
        failure {
            mail to: 'team@example.com',
                 subject: "Build Failed: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
                 body: "Build failed. Check console output."
        }
    }
}
# 変換後のGitHub Actions
name: Migrated from Jenkins

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

env:
  NODE_VERSION: '18'
  DOCKER_REGISTRY: 'myregistry.com'

jobs:
  build:
    name: Build Application
    runs-on: ubuntu-latest
    
    outputs:
      build-number: ${{ steps.build-number.outputs.number }}
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      
      - name: Generate build number
        id: build-number
        run: echo "number=${{ github.run_number }}" >> $GITHUB_OUTPUT
      
      - 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 application
        run: npm run build
      
      - name: Upload build artifacts
        uses: actions/upload-artifact@v3
        with:
          name: build-artifacts
          path: dist/

  test:
    name: Test Suite
    runs-on: ubuntu-latest
    needs: build
    
    strategy:
      matrix:
        test-type: [unit, e2e]
    
    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: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-artifacts
          path: dist/
      
      - name: Run tests
        run: npm run test:${{ matrix.test-type }}
      
      - name: Publish test results
        uses: dorny/test-reporter@v1
        if: success() || failure()
        with:
          name: ${{ matrix.test-type }} Tests
          path: test-results.xml
          reporter: jest-junit

  deploy:
    name: Deploy Application
    runs-on: ubuntu-latest
    needs: [build, test]
    if: github.ref == 'refs/heads/main'
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      
      - name: Login to registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.DOCKER_REGISTRY }}
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      
      - name: Build and push image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ env.DOCKER_REGISTRY }}/myapp:${{ needs.build.outputs.build-number }}
      
      - name: Notify on failure
        if: failure()
        uses: 8398a7/action-slack@v3
        with:
          status: failure
          channel: '#alerts'
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}
          message: |
            Build Failed: ${{ github.workflow }} - ${{ github.run_number }}
            Check the console output for details.

📊 移行比較表

機能 Jenkins CircleCI GitLab CI GitHub Actions 備考
セットアップ 複雑 簡単 中程度 最も簡単 GitHub統合
設定ファイル Groovy YAML YAML YAML GitHub Actionsが最も直感的
並列実行 matrix戦略が優秀
キャッシュ プラグイン 設定が最もシンプル
シークレット管理 プラグイン 環境別管理が優秀
コスト(中規模) 無料枠が大きい
学習コスト 広く普及
拡張性 Marketplaceが充実

6. 運用最適化・監視

📊 パフォーマンス最適化

高速ビルド戦略

# .github/workflows/optimized-ci.yml
name: Optimized CI Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  changes:
    name: Detect Changes
    runs-on: ubuntu-latest
    outputs:
      frontend: ${{ steps.changes.outputs.frontend }}
      backend: ${{ steps.changes.outputs.backend }}
      docs: ${{ steps.changes.outputs.docs }}
    steps:
      - uses: actions/checkout@v4
      - uses: dorny/paths-filter@v2
        id: changes
        with:
          filters: |
            frontend:
              - 'frontend/**'
              - 'package.json'
            backend:
              - 'backend/**'
              - 'requirements.txt'
            docs:
              - 'docs/**'
              - '*.md'

  frontend-ci:
    name: Frontend CI
    runs-on: ubuntu-latest
    needs: changes
    if: needs.changes.outputs.frontend == 'true'
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js with cache
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'
          cache-dependency-path: 'frontend/package-lock.json'
      
      - name: Restore node_modules cache
        uses: actions/cache@v3
        with:
          path: frontend/node_modules
          key: ${{ runner.os }}-nodemodules-${{ hashFiles('frontend/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-nodemodules-
      
      - name: Install dependencies
        run: npm ci --prefix frontend
      
      - name: Parallel build and test
        run: |
          npm run build --prefix frontend &
          npm run test --prefix frontend &
          wait

  backend-ci:
    name: Backend CI
    runs-on: ubuntu-latest
    needs: changes
    if: needs.changes.outputs.backend == 'true'
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Python with cache
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
          cache: 'pip'
          cache-dependency-path: 'backend/requirements.txt'
      
      - name: Install dependencies
        run: |
          cd backend
          pip install -r requirements.txt
      
      - name: Run tests
        run: |
          cd backend
          pytest --maxfail=1 --disable-warnings -q

  docs-check:
    name: Documentation Check
    runs-on: ubuntu-latest
    needs: changes
    if: needs.changes.outputs.docs == 'true'
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Check documentation
        run: |
          # ドキュメントの軽量チェック
          echo "Checking documentation..."
          # 実際のドキュメントビルド・リンクチェック等

📈 モニタリング・メトリクス

詳細メトリクス収集

# .github/workflows/metrics-collection.yml
name: CI/CD Metrics Collection

on:
  workflow_run:
    workflows: ["Main CI", "Deploy Pipeline"]
    types: [completed]

jobs:
  collect-metrics:
    name: Collect CI/CD Metrics
    runs-on: ubuntu-latest
    
    steps:
      - name: Collect workflow metrics
        uses: actions/github-script@v6
        with:
          script: |
            const workflowRun = context.payload.workflow_run;
            
            // ワークフロー実行時間の計算
            const startTime = new Date(workflowRun.created_at);
            const endTime = new Date(workflowRun.updated_at);
            const duration = (endTime - startTime) / 1000; // 秒
            
            // メトリクスデータの作成
            const metrics = {
              workflow_name: workflowRun.name,
              status: workflowRun.conclusion,
              duration_seconds: duration,
              commit_sha: workflowRun.head_sha,
              branch: workflowRun.head_branch,
              trigger_event: workflowRun.event,
              run_number: workflowRun.run_number,
              timestamp: workflowRun.created_at
            };
            
            // メトリクスをログ出力
            console.log('CI/CD Metrics:', JSON.stringify(metrics, null, 2));
            
            // 外部監視システムに送信DataDog、Prometheus等
            if (process.env.DATADOG_API_KEY) {
              await fetch('https://api.datadoghq.com/api/v1/series', {
                method: 'POST',
                headers: {
                  'Content-Type': 'application/json',
                  'DD-API-KEY': process.env.DATADOG_API_KEY
                },
                body: JSON.stringify({
                  series: [{
                    metric: 'github_actions.workflow.duration',
                    points: [[Math.floor(Date.now() / 1000), duration]],
                    tags: [
                      `workflow:${workflowRun.name}`,
                      `status:${workflowRun.conclusion}`,
                      `branch:${workflowRun.head_branch}`
                    ]
                  }]
                })
              });
            }
        env:
          DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }}
      
      - name: Generate weekly report
        if: github.event.schedule == '0 9 * * 1'  # 毎週月曜日
        uses: actions/github-script@v6
        with:
          script: |
            // 過去1週間のワークフロー実行データを取得
            const { data: runs } = await github.rest.actions.listWorkflowRunsForRepo({
              owner: context.repo.owner,
              repo: context.repo.repo,
              per_page: 100,
              created: `>=${new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString()}`
            });
            
            // メトリクス集計
            const metrics = runs.workflow_runs.reduce((acc, run) => {
              const duration = (new Date(run.updated_at) - new Date(run.created_at)) / 1000;
              
              if (!acc[run.name]) {
                acc[run.name] = {
                  total_runs: 0,
                  successful_runs: 0,
                  failed_runs: 0,
                  total_duration: 0,
                  avg_duration: 0
                };
              }
              
              acc[run.name].total_runs++;
              acc[run.name].total_duration += duration;
              
              if (run.conclusion === 'success') {
                acc[run.name].successful_runs++;
              } else if (run.conclusion === 'failure') {
                acc[run.name].failed_runs++;
              }
              
              acc[run.name].avg_duration = acc[run.name].total_duration / acc[run.name].total_runs;
              
              return acc;
            }, {});
            
            // レポート生成
            let report = '# GitHub Actions Weekly Report\n\n';
            
            for (const [workflow, data] of Object.entries(metrics)) {
              const successRate = ((data.successful_runs / data.total_runs) * 100).toFixed(2);
              
              report += `## ${workflow}\n`;
              report += `- **Total Runs**: ${data.total_runs}\n`;
              report += `- **Success Rate**: ${successRate}%\n`;
              report += `- **Average Duration**: ${Math.round(data.avg_duration)}s\n`;
              report += `- **Failed Runs**: ${data.failed_runs}\n\n`;
            }
            
            // Issueとしてレポートを投稿
            await github.rest.issues.create({
              owner: context.repo.owner,
              repo: context.repo.repo,
              title: `Weekly CI/CD Report - ${new Date().toISOString().split('T')[0]}`,
              body: report,
              labels: ['metrics', 'weekly-report']
            });

🎓 実践演習

演習1: フルスタックCI/CDパイプライン構築

  1. 多言語対応 - Node.js + Python のモノレポ
  2. 並列実行 - 言語別の独立したジョブ
  3. 条件分岐 - 変更検知による最適化
  4. 成果物管理 - アーティファクトの効率的な受け渡し

演習2: セキュリティファーストパイプライン

  1. コード解析 - CodeQL・Semgrep統合
  2. 依存関係スキャン - Snyk・Trivy活用
  3. シークレット検知 - TruffleHog導入
  4. コンテナセキュリティ - イメージスキャン自動化

演習3: 外部ツール移行プロジェクト

  1. 現状分析 - 既存CI/CDの機能・設定調査
  2. 移行戦略 - 段階的移行計画立案
  3. 並行運用 - リスク軽減・検証期間設定
  4. 完全移行 - 旧システム停止・運用移管

🔗 関連リソース

公式ドキュメント

移行・活用ツール

監視・最適化ツール


📝 まとめ

GitHub Actions を効果的に活用することで:

外部ツール不要 - Jenkins・CircleCIからの完全移行 コスト大幅削減 - インフラ・ライセンス費用の最適化
統合開発環境 - コードとCI/CDの一元管理 高度な自動化 - セキュリティ・品質・デプロイの自動化 スケーラビリティ - 企業レベルの大規模開発対応

次はGitHub Security編で、総合的なセキュリティ対策を学習しましょう。

🔗 関連ガイド

📖 学習フロー

graph LR
    A[リポジトリ基礎] --> B[Issues管理]
    B --> C[Pull Request]
    C --> D[GitHub Projects]
    D --> E[GitHub Actions]
    E --> F[Security] 
    F --> G[Pages]
    G --> H[完全活用]
    
    style A fill:#f3e5f5
    style B fill:#f3e5f5
    style C fill:#f3e5f5
    style D fill:#f3e5f5
    style E fill:#e1f5fe
    style F fill:#e8f5e8
    style G fill:#fff3e0
    style H fill:#fce4ec