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 }}
トラブルシューティング
よくある問題と解決策
-
ビルドが遅い
- キャッシュを活用
- 不要なステップを削除
- 並列実行を検討
-
シークレットが機能しない
- スコープを確認(リポジトリ/組織)
- 名前の大文字小文字を確認
- 環境設定を確認
-
特定の環境でのみ失敗
- 環境差異を調査
- Dockerを使用して統一
- ログを詳細に確認
まとめ
CI/CDパイプラインは、モダンな開発に欠かせない要素です。適切に設定することで:
- 品質向上: 自動テストで問題を早期発見
- 効率化: 手動作業を自動化
- 信頼性: 一貫したビルド・デプロイプロセス
最初は簡単なワークフローから始めて、徐々に高度な機能を追加していくことが成功の鍵です。
次のレッスンでは、大規模なリポジトリを効率的に扱う方法について学びます。