CI CD Pipeline Aufbau
CI/CD Pipeline: Automatisiertes Deployment
CI/CD automatisiert den Weg vom Code zur Production. Lernen Sie, wie Sie eine robuste Pipeline aufbauen.
CI vs. CD
┌─────────────────────────────────────────────────────────────────┐ │ CI/CD Pipeline │ ├─────────────────────┬───────────────────────────────────────────┤ │ Continuous │ Continuous Delivery / Deployment │ │ Integration │ │ ├─────────────────────┼───────────────────────────────────────────┤ │ • Code commiten │ • Staging Deployment │ │ • Build │ • Production Deployment │ │ • Lint/Format │ • Rollback-Strategie │ │ • Unit Tests │ • Blue/Green Deployment │ │ • Integration Tests │ • Feature Flags │ │ • Security Scans │ │ └─────────────────────┴───────────────────────────────────────────┘
Typische Pipeline-Stages
Push → Build → Test → Security → Deploy Staging → Deploy Production
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
Compile Unit SAST/DAST Smoke Tests Health Check
Assets Integ Deps Scan Manual QA Monitoring
Docker E2E
GitHub Actions Pipeline
# .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
NODE_VERSION: '20'
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
# Stage 1: Build & Test
build-and-test:
runs-on: ubuntu-latest
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: Lint
run: npm run lint
- name: Type check
run: npm run typecheck
- name: Unit tests
run: npm run test:unit -- --coverage
- name: Upload coverage
uses: codecov/codecov-action@v3
- name: Build
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build
path: dist/
# Stage 2: Integration Tests
integration-tests:
needs: build-and-test
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: --health-cmd pg_isready
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci
- name: Run integration tests
run: npm run test:integration
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
# Stage 3: Security Scan
security:
needs: build-and-test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Snyk
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
- name: Run Trivy
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
severity: 'CRITICAL,HIGH'
# Stage 4: Build Docker Image
docker:
needs: [integration-tests, security]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Login to Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
# Stage 5: Deploy to Staging
deploy-staging:
needs: docker
runs-on: ubuntu-latest
environment: staging
steps:
- name: Deploy to Staging
run: |
# Kubernetes deployment
kubectl set image deployment/myapp \
myapp=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
- name: Smoke tests
run: |
curl -f https://staging.example.com/health || exit 1
# Stage 6: Deploy to Production
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
- name: Deploy to Production
run: |
kubectl set image deployment/myapp \
myapp=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
- name: Health check
run: |
for i in {1..10}; do
curl -f https://example.com/health && exit 0
sleep 10
done
exit 1
GitLab CI Pipeline
# .gitlab-ci.yml
stages:
- build
- test
- security
- deploy
variables:
NODE_VERSION: "20"
build:
stage: build
image: node:${NODE_VERSION}
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 hour
test:
stage: test
image: node:${NODE_VERSION}
script:
- npm ci
- npm run test
coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'
security:
stage: security
image: node:${NODE_VERSION}
script:
- npm audit --audit-level=high
allow_failure: true
deploy-staging:
stage: deploy
environment:
name: staging
url: https://staging.example.com
script:
- ./deploy.sh staging
only:
- main
deploy-production:
stage: deploy
environment:
name: production
url: https://example.com
script:
- ./deploy.sh production
when: manual
only:
- main
Deployment-Strategien
# Rolling Update (Standard) ┌───────────────────────┐ │ v1 v1 v1 v1 │ Start │ v1 v1 v1 v2 │ 1 Pod updated │ v1 v1 v2 v2 │ 2 Pods updated │ v2 v2 v2 v2 │ Complete └───────────────────────┘ # Blue/Green ┌───────────────────────┐ │ Blue (v1) ◄── Traffic │ │ Green (v2) - idle │ Deploy v2 to Green │ Blue (v1) - idle │ │ Green (v2) ◄─ Traffic│ Switch traffic └───────────────────────┘ # Canary ┌───────────────────────┐ │ 95% ──► v1 │ │ 5% ──► v2 │ Test with small % │ 50% ──► v1 │ │ 50% ──► v2 │ Gradually increase └───────────────────────┘
Rollback
# Kubernetes
kubectl rollout undo deployment/myapp
kubectl rollout undo deployment/myapp --to-revision=2
# GitHub Actions - Rollback Workflow
name: Rollback
on:
workflow_dispatch:
inputs:
version:
description: 'Version to rollback to'
required: true
jobs:
rollback:
runs-on: ubuntu-latest
steps:
- name: Rollback
run: |
kubectl set image deployment/myapp \
myapp=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ inputs.version }}
💡 Tipp:
Überwachen Sie Ihre Deployments mit dem Enjyn Status Monitor und erhalten Sie Alerts bei Fehlern.