メインコンテンツへスキップ
レッスン 12 / 15推定時間: 30

GitHub Actions/GitLab CI

CI/CDパイプラインを構築し、自動テスト・自動デプロイを実現する方法を学びましょう

このレッスンの学習目標

  • CI/CDの概念とメリットを理解する
  • GitHub ActionsとGitLab CIの基本を習得する
  • 実践的なパイプラインを構築できる

CI/CDとは?

CI/CD(Continuous Integration / Continuous Delivery)は、コードの変更を自動的にビルド、テスト、デプロイするプロセスです。

なぜCI/CDが重要?

🐛 品質の問題

  • 「ローカルでは動くが、本番で動かない」
  • 「他の人の環境でビルドできない」
  • 「テストを忘れてマージしてしまう」

⏰ 時間の無駄

  • 「手動でテストを実行するのが面倒」
  • 「デプロイ手順が複雑で時間がかかる」
  • 「リリース作業でミスが発生する」

📊 可視性の欠如

  • 「現在のコード品質が分からない」
  • 「テストカバレッジが不明」
  • 「ビルドの成否が共有されない」

GitHub Actions

基本構造

# .github/workflows/ci.yml
name: CI

# トリガー設定
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

# ジョブ定義
jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          
      - name: Install dependencies
        run: npm ci
        
      - name: Run tests
        run: npm test
        
      - name: Run linter
        run: npm run lint

実践的なワークフロー例

1. 複数環境でのテスト

name: Cross-platform Test

on: [push, pull_request]

jobs:
  test:
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [16.x, 18.x, 20.x]
    
    runs-on: ${{ matrix.os }}
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
          
      - run: npm ci
      - run: npm test

2. 自動デプロイ

name: Deploy

on:
  push:
    branches: [ main ]
    tags: [ 'v*' ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Build
        run: |
          npm ci
          npm run build
          
      - name: Deploy to Production
        if: startsWith(github.ref, 'refs/tags/v')
        env:
          DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
        run: |
          # デプロイスクリプト
          ./scripts/deploy.sh production
          
      - name: Deploy to Staging
        if: github.ref == 'refs/heads/main'
        run: |
          ./scripts/deploy.sh staging

シークレットの管理

name: Secure Deploy

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1
          
      - name: Deploy to S3
        run: |
          aws s3 sync ./build s3://my-bucket

GitLab CI

基本構造

# .gitlab-ci.yml
stages:
  - build
  - test
  - deploy

variables:
  NODE_VERSION: "18"

# ジョブ定義
build:
  stage: build
  image: node:${NODE_VERSION}
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - build/
    expire_in: 1 hour

test:
  stage: test
  image: node:${NODE_VERSION}
  script:
    - npm ci
    - npm test
  coverage: '/Coverage: \d+\.\d+%/'

deploy:
  stage: deploy
  script:
    - echo "Deploying to production"
  only:
    - main

高度な機能

1. パイプライン条件

# 条件付き実行
test:unit:
  stage: test
  script:
    - npm run test:unit
  except:
    - tags

test:e2e:
  stage: test
  script:
    - npm run test:e2e
  only:
    - main
    - develop
  when: manual  # 手動実行

deploy:production:
  stage: deploy
  script:
    - ./deploy.sh production
  only:
    - tags
  when: manual
  environment:
    name: production
    url: https://example.com

2. Docker統合

build-image:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  variables:
    DOCKER_DRIVER: overlay2
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:latest

実践的なCI/CDパイプライン

プルリクエスト/マージリクエストのワークフロー

# GitHub Actions
name: PR Check

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  quality-check:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0  # For SonarCloud
          
      - name: Code Quality
        run: |
          npm ci
          npm run lint
          npm run type-check
          
      - name: Test with Coverage
        run: |
          npm run test:coverage
          
      - name: SonarCloud Scan
        uses: SonarSource/sonarcloud-github-action@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          
      - name: Comment PR
        uses: actions/github-script@v6
        if: always()
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: '✅ All checks passed!'
            })

セマンティックリリース

name: Release

on:
  push:
    branches: [ main ]

jobs:
  release:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
          
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          
      - name: Install dependencies
        run: npm ci
        
      - name: Build
        run: npm run build
        
      - name: Semantic Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npx semantic-release

実践演習

CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$

ファイルツリー

/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log

CI/CDのベストプラクティス

1. 高速化の工夫

# キャッシュの活用
- name: Cache node modules
  uses: actions/cache@v3
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

# 並列実行
jobs:
  test:
    strategy:
      matrix:
        test-suite: [unit, integration, e2e]
    steps:
      - run: npm run test:${{ matrix.test-suite }}

2. セキュリティ対策

# Dependabotの設定
# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10

3. 通知設定

# Slack通知
- name: Slack Notification
  if: always()
  uses: 8398a7/action-slack@v3
  with:
    status: ${{ job.status }}
    text: "Build ${{ job.status }}"
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

トラブルシューティング

よくある問題と解決策

  1. ビルドが遅い

    • キャッシュを活用
    • 不要なステップを削除
    • 並列実行を検討
  2. シークレットが機能しない

    • スコープを確認(リポジトリ/組織)
    • 名前の大文字小文字を確認
    • 環境設定を確認
  3. 特定の環境でのみ失敗

    • 環境差異を調査
    • Dockerを使用して統一
    • ログを詳細に確認

まとめ

CI/CDパイプラインは、モダンな開発に欠かせない要素です。適切に設定することで:

  1. 品質向上: 自動テストで問題を早期発見
  2. 効率化: 手動作業を自動化
  3. 信頼性: 一貫したビルド・デプロイプロセス

最初は簡単なワークフローから始めて、徐々に高度な機能を追加していくことが成功の鍵です。

次のレッスンでは、大規模なリポジトリを効率的に扱う方法について学びます。

さらに学習を続けるには

素晴らしい学習ペースです!次のレッスンに進むには、無料会員登録をお願いします。無料会員では各コース3レッスンまで学習できます。

無料で続きを学ぶ

各コース3レッスンまで学習可能

学習進捗の自動保存

コース修了証明書の発行