Zum Hauptinhalt springen

πŸš€ Was ist CI/CD?

πŸ“– Definition​

CI/CD steht fΓΌr Continuous Integration (Kontinuierliche Integration) und Continuous Deployment (Kontinuierliches Deployment), eine Entwicklungsmethodik, die Code-Γ„nderungen automatisch testet und bereitstellt. CI erstellt und testet Code automatisch bei jeder ZusammenfΓΌhrung, wΓ€hrend CD getesteten Code automatisch in Produktionsumgebungen bereitstellt. Dies ermΓΆglicht eine schnellere Fehlererkennung und kΓΌrzere Bereitstellungszyklen.

🎯 Verstehen durch Analogien​

Fabrikautomatisierungslinie​

Traditionelle Entwicklung (Manuell)
Entwickler 1 β†’ Code schreiben
Entwickler 2 β†’ Code schreiben
Entwickler 3 β†’ Code schreiben
↓
Eine Woche spΓ€ter
↓
Teamleiter fΓΌhrt manuell zusammen
↓
Konflikte auftreten! 😱
↓
Manuelles Testen
↓
Fehler gefunden! 😱
↓
Manuelles Deployment
↓
Deployment fehlgeschlagen! 😱

CI/CD (Automatisiert)
Entwickler 1 β†’ Code pushen β†’ Auto-Test βœ… β†’ Auto-Deploy πŸš€
Entwickler 2 β†’ Code pushen β†’ Auto-Test βœ… β†’ Auto-Deploy πŸš€
Entwickler 3 β†’ Code pushen β†’ Auto-Test ❌ β†’ Sofortige Benachrichtigung!
(Probleme sofort erkannt und behoben)

Essenslieferung​

Manuelles Deployment = Direkte Lieferung
1. Essen zubereiten (Entwicklung)
2. Verpackung prΓΌfen (Testen)
3. Adresse bestΓ€tigen (Konfiguration)
4. Fahren und liefern (Deployment)
5. KundenbestΓ€tigung (Verifizierung)
β†’ ZeitaufwΓ€ndig, fehleranfΓ€llig

CI/CD = Automatisches Liefersystem
1. Essen zubereiten (Entwicklung)
2. Automatische Verpackung (Auto-Build)
3. Automatische QualitΓ€tsprΓΌfung (Auto-Test)
4. Roboter-Automatiklieferung (Auto-Deployment)
5. Echtzeit-Tracking (Monitoring)
β†’ Schnell und prΓ€zise

βš™οΈ Funktionsweise​

1. CI/CD-Pipeline​

Code Push
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ CI: Kontinuierliche β”‚
β”‚ Integration β”‚
β”‚ β”‚
β”‚ 1. Code auschecken β”‚
β”‚ 2. AbhΓ€ngigkeiten installierenβ”‚
β”‚ 3. Lint-PrΓΌfung β”‚
β”‚ 4. Build β”‚
β”‚ 5. Unit-Tests β”‚
β”‚ 6. Integrationstests β”‚
β”‚ β”‚
β”‚ βœ… Alle erfolgreich β”‚
β”‚ ❌ Beliebiger Fehler β†’ Stop β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ CD: Kontinuierliches β”‚
β”‚ Deployment β”‚
β”‚ β”‚
β”‚ 1. In Staging deployen β”‚
β”‚ 2. E2E-Tests β”‚
β”‚ 3. In Produktion deployen β”‚
β”‚ 4. Health Check β”‚
β”‚ 5. Benachrichtigungen sendenβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓
πŸŽ‰ Deployment abgeschlossen!

2. Traditioneller Ansatz vs CI/CD​

Traditioneller Ansatz
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Montag β”‚
β”‚ - Entwickler A: Feature 1 β”‚
β”‚ - Entwickler B: Feature 2 β”‚
β”‚ - Entwickler C: Fehler beheben β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Dienstag-Donnerstag β”‚
β”‚ - Individuelle Entwicklung fortsetzenβ”‚
β”‚ - Konfliktrisiko steigt 😰 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Freitag (Integrationstag) β”‚
β”‚ - Allen Code zusammenfΓΌhren β”‚
β”‚ - Ganzen Tag Konflikte lΓΆsen 😱 β”‚
β”‚ - Tests ausfΓΌhren β†’ Viele Fehler β”‚
β”‚ - Überstunden bis Wochenende 😭 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

CI/CD-Ansatz
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Jeden Tag, jeden Commit β”‚
β”‚ β”‚
β”‚ Entwickler A: Code pushen β”‚
β”‚ β†’ Auto-Test βœ… β”‚
β”‚ β†’ Auto-Deploy πŸš€ β”‚
β”‚ β†’ In 3 Minuten in Produktion β”‚
β”‚ β”‚
β”‚ Entwickler B: Code pushen β”‚
β”‚ β†’ Auto-Test ❌ β”‚
β”‚ β†’ Sofortige Benachrichtigung β”‚
β”‚ β†’ Sofort beheben (5 Min) β”‚
β”‚ β”‚
β”‚ - Konflikte minimiert β”‚
β”‚ - Schnelle Fehlererkennung β”‚
β”‚ - PΓΌnktlich Feierabend 😊 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

3. CI/CD-Komponenten​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Versionskontrolle β”‚
β”‚ Git, GitHub, GitLab β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓ Push
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ CI-Server β”‚
β”‚ GitHub Actions, Jenkins, CircleCI β”‚
β”‚ - Code auschecken β”‚
β”‚ - Automatischer Build β”‚
β”‚ - Automatische Tests β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓ Pass
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Artefakt-Repository β”‚
β”‚ Docker Hub, npm Registry β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓ Deploy
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Deployment β”‚
β”‚ AWS, Heroku, Vercel, Netlify β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓ Monitor
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Monitoring β”‚
β”‚ Sentry, DataDog, CloudWatch β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ’‘ Praxisbeispiele​

GitHub Actions Grundbeispiel​

# .github/workflows/ci.yml
# CI/CD-Pipeline fΓΌr Node.js-Projekt

name: CI/CD Pipeline

# Trigger: Bei Push zu main oder PR-Erstellung
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]

# Umgebungsvariablen
env:
NODE_VERSION: '18'

# Job-Definitionen
jobs:
# ========== Job 1: Tests ==========
test:
name: Tests und Lint
runs-on: ubuntu-latest # Auf Ubuntu ausfΓΌhren

steps:
# 1. Code auschecken
- name: Code auschecken
uses: actions/checkout@v3

# 2. Node.js einrichten
- name: Node.js einrichten
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm' # npm-Cache verwenden

# 3. AbhΓ€ngigkeiten installieren
- name: AbhΓ€ngigkeiten installieren
run: npm ci # Schneller und stabiler als npm install

# 4. Lint-PrΓΌfung
- name: Lint ausfΓΌhren
run: npm run lint

# 5. Unit-Tests
- name: Tests ausfΓΌhren
run: npm test

# 6. Code-Abdeckung
- name: Abdeckung hochladen
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}

# ========== Job 2: Build ==========
build:
name: Build
needs: test # Nur ausfΓΌhren wenn test erfolgreich
runs-on: ubuntu-latest

steps:
- name: Code auschecken
uses: actions/checkout@v3

- name: Node.js einrichten
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: AbhΓ€ngigkeiten installieren
run: npm ci

# Produktions-Build
- name: Produktions-Build
run: npm run build
env:
NODE_ENV: production

# Build-Artefakte hochladen
- name: Build-Artefakte hochladen
uses: actions/upload-artifact@v3
with:
name: build-files
path: dist/
retention-days: 7

# ========== Job 3: Deployment ==========
deploy:
name: Produktions-Deployment
needs: build # Nur ausfΓΌhren wenn build erfolgreich
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' # Nur main-Branch deployen

steps:
- name: Code auschecken
uses: actions/checkout@v3

# Build-Artefakte herunterladen
- name: Build-Artefakte herunterladen
uses: actions/download-artifact@v3
with:
name: build-files
path: dist/

# Auf Vercel deployen
- name: Auf Vercel deployen
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'

# Slack-Benachrichtigung
- name: Slack-Benachrichtigung
if: always() # UnabhΓ€ngig von Erfolg/Misserfolg ausfΓΌhren
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Deployment ${{ job.status }}!'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Docker Build und Deployment​

# .github/workflows/docker.yml
# Docker Image Build und Deployment

name: Docker CI/CD

on:
push:
branches: [ main ]
tags:
- 'v*' # AusfΓΌhren bei Tags wie v1.0.0

env:
DOCKER_IMAGE: myapp
DOCKER_REGISTRY: docker.io

jobs:
docker:
name: Docker Build und Push
runs-on: ubuntu-latest

steps:
- name: Code auschecken
uses: actions/checkout@v3

# Docker-Metadaten einrichten
- name: Docker-Metadaten extrahieren
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha

# Docker Buildx einrichten (Multi-Plattform-Build)
- name: Docker Buildx einrichten
uses: docker/setup-buildx-action@v2

# Bei Docker Hub anmelden
- name: Bei Docker Hub anmelden
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

# Docker Image bauen und pushen
- name: Docker Image bauen und pushen
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha # GitHub Actions Cache verwenden
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64 # Multi-Plattform

# Deployment (Per SSH auf Server zugreifen und Container neu starten)
- name: Server-Deployment
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
docker pull ${{ env.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:latest
docker stop myapp || true
docker rm myapp || true
docker run -d \
--name myapp \
-p 3000:3000 \
--restart unless-stopped \
${{ env.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}:latest
docker system prune -af

Pull Request automatische Validierung​

# .github/workflows/pr.yml
# Bei PR-Erstellung automatisch validieren

name: Pull Request Check

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

jobs:
# ========== Code-QualitΓ€tsprΓΌfung ==========
lint:
name: Lint und Format Check
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Node.js einrichten
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'

- name: AbhΓ€ngigkeiten installieren
run: npm ci

# ESLint
- name: ESLint ausfΓΌhren
run: npm run lint

# Prettier
- name: Prettier-PrΓΌfung
run: npm run format:check

# TypeScript-Typ-PrΓΌfung
- name: TypeScript-Typ-PrΓΌfung
run: npm run type-check

# ========== Tests ==========
test:
name: Tests
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [16, 18, 20] # Tests auf mehreren Node-Versionen

steps:
- uses: actions/checkout@v3

- name: Node.js ${{ matrix.node-version }} einrichten
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

- name: AbhΓ€ngigkeiten installieren
run: npm ci

- name: Tests ausfΓΌhren
run: npm test -- --coverage

- name: Test-Ergebnisse hochladen
uses: actions/upload-artifact@v3
if: always()
with:
name: test-results-${{ matrix.node-version }}
path: coverage/

# ========== SicherheitsprΓΌfung ==========
security:
name: SicherheitsprΓΌfung
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Node.js einrichten
uses: actions/setup-node@v3
with:
node-version: '18'

# npm audit
- name: npm-SicherheitsprΓΌfung
run: npm audit --audit-level=moderate

# Snyk-Sicherheitsscan
- name: Snyk-Sicherheitsscan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

# ========== Performance-Tests ==========
performance:
name: Performance-Tests
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Node.js einrichten
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'

- name: AbhΓ€ngigkeiten installieren
run: npm ci

- name: Build
run: npm run build

# Lighthouse CI
- name: Lighthouse CI
uses: treosh/lighthouse-ci-action@v9
with:
urls: |
http://localhost:3000
uploadArtifacts: true

# ========== PR-Kommentar ==========
comment:
name: PR-Kommentar
needs: [lint, test, security]
runs-on: ubuntu-latest
if: always()

steps:
- name: PR-Kommentar erstellen
uses: actions/github-script@v6
with:
script: |
const statuses = {
lint: '${{ needs.lint.result }}',
test: '${{ needs.test.result }}',
security: '${{ needs.security.result }}'
};

let message = '## πŸ€– CI-PrΓΌfungsergebnis\n\n';

for (const [job, status] of Object.entries(statuses)) {
const emoji = status === 'success' ? 'βœ…' : '❌';
message += `${emoji} **${job}**: ${status}\n`;
}

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: message
});

Zeitplanbasierte Aufgaben​

# .github/workflows/scheduled.yml
# RegelmÀßig ausgeführte Aufgaben

name: Scheduled Tasks

on:
schedule:
# TΓ€glich um 9 Uhr (UTC 0 Uhr)
- cron: '0 0 * * *'
workflow_dispatch: # Manuelle AusfΓΌhrung auch mΓΆglich

jobs:
# ========== AbhΓ€ngigkeitsaktualisierungsprΓΌfung ==========
dependency-check:
name: AbhΓ€ngigkeitsaktualisierungen prΓΌfen
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Node.js einrichten
uses: actions/setup-node@v3
with:
node-version: '18'

# npm outdated prΓΌfen
- name: Veraltete Pakete prΓΌfen
run: npm outdated || true

# Dependabot-Alternative
- name: Aktualisierbare Pakete prΓΌfen
run: |
npx npm-check-updates

# ========== Backup ==========
backup:
name: Datenbank-Backup
runs-on: ubuntu-latest

steps:
- name: Datenbank sichern
run: |
# In der Praxis Datenbank-Backup-Skript ausfΓΌhren
echo "Datenbank wird gesichert..."

# Auf S3 hochladen
- name: Backup auf S3 hochladen
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-2

- name: S3-Upload
run: |
aws s3 cp backup.sql s3://my-backups/$(date +%Y%m%d).sql

# ========== Performance-Monitoring ==========
performance-monitor:
name: Performance-Monitoring
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Lighthouse ausfΓΌhren
uses: treosh/lighthouse-ci-action@v9
with:
urls: |
https://myapp.com
uploadArtifacts: true

# Bei Performance-Degradation Slack-Benachrichtigung
- name: Performance-Degradation-Benachrichtigung
if: failure()
uses: 8398a7/action-slack@v3
with:
status: failure
text: '⚠️ Website-Performance ist gesunken!'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Multi-Umgebungs-Deployment​

# .github/workflows/multi-env.yml
# Deployment nach Umgebung: Entwicklung, Staging, Produktion

name: Multi-Environment Deployment

on:
push:
branches:
- develop # Entwicklungsumgebung
- staging # Staging-Umgebung
- main # Produktionsumgebung

jobs:
deploy:
name: Deployment
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Node.js einrichten
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'

- name: AbhΓ€ngigkeiten installieren
run: npm ci

# Build je nach Umgebung
- name: Build
run: npm run build
env:
NODE_ENV: ${{
github.ref == 'refs/heads/main' && 'production' ||
github.ref == 'refs/heads/staging' && 'staging' ||
'development'
}}

# Entwicklungsumgebungs-Deployment
- name: Entwicklungsumgebungs-Deployment
if: github.ref == 'refs/heads/develop'
run: |
echo "Auf Entwicklungsumgebung deployen..."
# Entwicklungsserver-Deployment-Befehl
env:
API_URL: https://api-dev.myapp.com

# Staging-Umgebungs-Deployment
- name: Staging-Umgebungs-Deployment
if: github.ref == 'refs/heads/staging'
run: |
echo "Auf Staging-Umgebung deployen..."
# Staging-Server-Deployment-Befehl
env:
API_URL: https://api-staging.myapp.com

# Produktionsumgebungs-Deployment
- name: Produktionsumgebungs-Deployment
if: github.ref == 'refs/heads/main'
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: task-definition.json
service: myapp-service
cluster: production-cluster
wait-for-service-stability: true
env:
API_URL: https://api.myapp.com

# Health Check nach Deployment
- name: Health Check
run: |
sleep 30 # 30 Sekunden warten

URL=${{
github.ref == 'refs/heads/main' && 'https://myapp.com' ||
github.ref == 'refs/heads/staging' && 'https://staging.myapp.com' ||
'https://dev.myapp.com'
}}

STATUS=$(curl -s -o /dev/null -w "%{http_code}" $URL/health)

if [ $STATUS -eq 200 ]; then
echo "βœ… Health Check erfolgreich"
else
echo "❌ Health Check fehlgeschlagen: $STATUS"
exit 1
fi

# Deployment-Erfolg-Benachrichtigung
- name: Deployment-Benachrichtigung
if: success()
uses: 8398a7/action-slack@v3
with:
status: success
text: |
πŸš€ Deployment abgeschlossen!
Umgebung: ${{ github.ref_name }}
Commit: ${{ github.sha }}
webhook_url: ${{ secrets.SLACK_WEBHOOK }}

πŸ€” HΓ€ufig gestellte Fragen​

F1. Was sind die Vorteile der EinfΓΌhrung von CI/CD?​

A:

βœ… Hauptvorteile:

1. Schnellere Fehlererkennung
Traditionell: Nach einer Woche entdeckt
CI/CD: Innerhalb von 5 Minuten entdeckt
β†’ 90% Reduzierung der Behebungskosten

2. VerkΓΌrzte Deployment-Zeit
Traditionell: 2 Stunden manuelles Deployment
CI/CD: 5 Minuten automatisches Deployment
β†’ Mehrere Deployments pro Tag mΓΆglich

3. Verbesserte Code-QualitΓ€t
- Automatische Lint- und Tests
- Automatisierte Code-Review
- Weniger Fehler

4. ErhΓΆhte EntwicklerproduktivitΓ€t
- Manuelle Aufgaben eliminieren
- Wiederholende Arbeit automatisieren
- Nur auf Entwicklung konzentrieren

5. ErhΓΆhte StabilitΓ€t
- Automatische Tests
- Automatisches Rollback
- Konsistenter Deployment-Prozess

6. Verbesserte Zusammenarbeit
- Code-Konflikte minimieren
- Schnelles Feedback
- Transparenter Prozess

Praxisfall:
Unternehmen A: Vor CI/CD
- Deployment: 1x pro Monat
- Deployment-Zeit: 4 Stunden
- Fehlerquote: 30%
- Fehlererkennungszeit: Durchschnittlich 3 Tage

Unternehmen A: Nach CI/CD
- Deployment: 10x pro Tag
- Deployment-Zeit: 5 Minuten
- Fehlerquote: 5%
- Fehlererkennungszeit: Durchschnittlich 10 Minuten

F2. GitHub Actions vs Jenkins vs CircleCI?​

A:

// ========== GitHub Actions ==========
Vorteile:
- Perfekte GitHub-Integration
- Kostenlos (ΓΆffentliche Repos, 2000 Min/Monat kostenlos)
- Einfache Einrichtung (YAML-Dateien)
- Verschiedene Actions im Marketplace

Nachteile:
- GitHub-abhΓ€ngig
- Komplexe Workflows eingeschrΓ€nkt

Am besten fΓΌr:
- GitHub verwenden
- Einfaches CI/CD
- Schneller Start erforderlich

Beispiel:
name: CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: npm test

// ========== Jenkins ==========
Vorteile:
- Am Γ€ltesten und ausgereiftesten
- Umfangreiches Plugin-Γ–kosystem
- VollstΓ€ndige Anpassung
- Self-hosted (keine Kosten)

Nachteile:
- Komplexe Einrichtung
- Veraltete UI
- Wartung erforderlich
- Steile Lernkurve

Am besten fΓΌr:
- On-Premises-Umgebung
- Komplexe Pipelines
- Legacy-System-Integration

// ========== CircleCI ==========
Vorteile:
- Schnelle Build-Geschwindigkeit
- Hervorragende Docker-UnterstΓΌtzung
- Starke Parallelisierung
- Intuitive UI

Nachteile:
- Kostenpflichtig (eingeschrΓ€nktes kostenloses Tier)
- Nur GitHub/GitLab-UnterstΓΌtzung

Am besten fΓΌr:
- Leistung kritisch
- Intensive Docker-Nutzung
- Parallele Tests erforderlich

// ========== Vergleichstabelle ==========
Merkmal | GitHub Actions | Jenkins | CircleCI
---------------|----------------|---------|----------
Preis | Kostenlos(begr.)| Kostenlos| Bezahlt
Einrichtung | Einfach | Schwer | Mittel
Leistung | Mittel | Hoch | Hoch
Integration | GitHub perfekt | Generisch| Generisch
Wartung | Nicht nΓΆtig | NΓΆtig | Nicht nΓΆtig
Docker | Mittel | Gut | Sehr gut

Empfehlung:
- Kleines Team, GitHub nutzen β†’ GitHub Actions
- Großes Team, komplexe Anforderungen β†’ Jenkins
- Leistung kritisch, Budget vorhanden β†’ CircleCI

F3. Wie verwaltet man geheime SchlΓΌssel (Secrets)?​

A:

# ========== GitHub Secrets Einrichtung ==========
# Repository β†’ Settings β†’ Secrets and variables β†’ Actions

# Verwendung
- name: Deployment
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: npm run deploy

# ========== Umgebungsspezifische Secrets ==========
# Repository β†’ Settings β†’ Environments

# Produktionsumgebung
environment: production
env:
API_URL: ${{ secrets.PROD_API_URL }}

# Staging-Umgebung
environment: staging
env:
API_URL: ${{ secrets.STAGING_API_URL }}

# ========== Sicherheits-Best Practices ==========

# βœ… Gutes Beispiel
- name: Deployment
env:
# Von Secrets abrufen
AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }}
AWS_SECRET_KEY: ${{ secrets.AWS_SECRET_KEY }}
run: |
# Umgebungsvariablen verwenden
aws s3 sync dist/ s3://my-bucket

# ❌ Schlechtes Beispiel
- name: Deployment
run: |
# Im Code hartkodiert (absolut verboten!)
export AWS_ACCESS_KEY="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

# ========== .env-Datei erstellen ==========
- name: .env-Datei erstellen
run: |
cat << EOF > .env
API_URL=${{ secrets.API_URL }}
DATABASE_URL=${{ secrets.DATABASE_URL }}
JWT_SECRET=${{ secrets.JWT_SECRET }}
EOF

# ========== Docker Secrets ==========
- name: Docker Build
env:
DOCKER_BUILDKIT: 1
run: |
docker build \
--secret id=api_key,env=API_KEY \
--secret id=db_url,env=DATABASE_URL \
-t myapp .

# Dockerfile
# syntax=docker/dockerfile:1
FROM node:18
RUN --mount=type=secret,id=api_key \
API_KEY=$(cat /run/secrets/api_key) npm install

# ========== Vault verwenden (Fortgeschritten) ==========
- name: Secrets von HashiCorp Vault abrufen
uses: hashicorp/vault-action@v2
with:
url: https://vault.mycompany.com
token: ${{ secrets.VAULT_TOKEN }}
secrets: |
secret/data/production api_key | API_KEY ;
secret/data/production db_url | DATABASE_URL

F4. Was passiert, wenn Tests fehlschlagen?​

A:

# ========== Standardverhalten: Pipeline stoppen ==========
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Tests ausfΓΌhren
run: npm test
# Bei Test-Fehler β†’ hier stoppen
# Folgende Schritte werden nicht ausgefΓΌhrt

deploy:
needs: test # Wird nur ausgefΓΌhrt wenn test erfolgreich
runs-on: ubuntu-latest
steps:
- name: Deployment
run: npm run deploy
# Bei test-Fehler wird dieser Schritt nicht ausgefΓΌhrt βœ…

# ========== Bei Fehler trotzdem fortsetzen ==========
- name: Tests ausfΓΌhren
run: npm test
continue-on-error: true # Bei Fehler fortsetzen
# ⚠️ Nicht empfohlen

# ========== Bedingte AusfΓΌhrung ==========
- name: Benachrichtigung bei Fehler
if: failure() # Nur wenn vorheriger Schritt fehlgeschlagen
uses: 8398a7/action-slack@v3
with:
status: failure
text: '❌ Test fehlgeschlagen!'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}

- name: Bei Erfolg deployen
if: success() # Nur wenn alle Schritte erfolgreich
run: npm run deploy

- name: Immer ausfΓΌhren
if: always() # UnabhΓ€ngig von Erfolg/Misserfolg
run: npm run cleanup

# ========== Wiederholungsversuche ==========
- name: Instabile Tests (Wiederholungsversuche)
uses: nick-invision/retry@v2
with:
timeout_minutes: 10
max_attempts: 3
command: npm run test:e2e

# ========== Fehlerbehandlungsbeispiel ==========
- name: Tests
id: test
run: npm test

- name: Issue erstellen bei Test-Fehler
if: failure() && steps.test.outcome == 'failure'
uses: actions/github-script@v6
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: '❌ Test fehlgeschlagen',
body: 'Tests sind fehlgeschlagen. Überprüfung erforderlich.',
labels: ['bug', 'ci']
});

# ========== Rollback ==========
- name: Deployment
id: deploy
run: npm run deploy

- name: Bei Deployment-Fehler Rollback
if: failure() && steps.deploy.outcome == 'failure'
run: |
echo "Deployment fehlgeschlagen! Rollback zur vorherigen Version..."
npm run rollback

F5. Wie kann man Kosten senken?​

A:

# ========== Caching nutzen ==========
- name: Node.js einrichten
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm' # npm-Caching (50% schnellerer Build)

- name: AbhΓ€ngigkeiten cachen
uses: actions/cache@v3
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-

# ========== Bedingte AusfΓΌhrung ==========
on:
push:
branches: [ main ]
paths: # Nur bei Γ„nderung bestimmter Dateien ausfΓΌhren
- 'src/**'
- 'package.json'
# Bei README.md-Γ„nderung nicht ausfΓΌhren β†’ Kostenersparnis

# ========== Gleichzeitige AusfΓΌhrung begrenzen ==========
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # Vorherige AusfΓΌhrung abbrechen
# β†’ Verhindert unnΓΆtige doppelte AusfΓΌhrungen

# ========== Self-hosted Runner ==========
# Eigenen Server verwenden (kostenlos)
jobs:
build:
runs-on: self-hosted # Verbraucht keine GitHub Actions-Minuten
steps:
- run: npm run build

# ========== Nur kurze Jobs ausfΓΌhren ==========
- name: GeΓ€nderte Dateien prΓΌfen
id: changes
uses: dorny/paths-filter@v2
with:
filters: |
frontend:
- 'frontend/**'
backend:
- 'backend/**'

- name: Frontend-Tests
if: steps.changes.outputs.frontend == 'true'
run: npm run test:frontend
# Nur bei Frontend-Γ„nderung ausfΓΌhren β†’ Zeitersparnis

- name: Backend-Tests
if: steps.changes.outputs.backend == 'true'
run: npm run test:backend

# ========== Kostenbeispiel ==========
# GitHub Actions Free Tier:
# - Γ–ffentliche Repos: Unbegrenzt
# - Private Repos: 2000 Minuten/Monat

# Vor Optimierung:
# - VollstΓ€ndige Tests bei jedem Commit (20 Min)
# - 10x Push pro Tag
# - Monatliche Nutzung: 10 Γ— 20 Γ— 30 = 6000 Min
# - Überkosten: (6000 - 2000) Γ— $0.008 = $32

# Nach Optimierung:
# - 10 Min durch Caching gespart
# - Nur geΓ€nderte Teile testen
# - Durchschnittliche Build-Zeit 5 Min
# - Monatliche Nutzung: 10 Γ— 5 Γ— 30 = 1500 Min
# - Kosten: $0 (innerhalb Free Tier)
# β†’ $32/Monat gespart!

πŸŽ“ NΓ€chste Schritte​

Nachdem Sie CI/CD verstanden haben, lernen Sie diese Themen:

  1. Was ist Git? (Noch zu schreiben) - Grundlagen der Versionskontrolle
  2. Was ist Docker? (Noch zu schreiben) - Containerisiertes Deployment
  3. Was ist TDD? (Noch zu schreiben) - Testgetriebene Entwicklung

Ausprobieren​

# ========== 1. Mit GitHub Actions beginnen ==========

# 1) Workflow-Datei im Repository erstellen
mkdir -p .github/workflows
cat > .github/workflows/ci.yml << 'EOF'
name: CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Node.js einrichten
uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm test
EOF

# 2) Commit und Push
git add .github/workflows/ci.yml
git commit -m "Add CI workflow"
git push

# 3) Actions-Tab auf GitHub ansehen
# β†’ Den automatisch laufenden Workflow sehen!

# ========== 2. Lokal testen (act) ==========
# Mit act GitHub Actions lokal testen

# act installieren (macOS)
brew install act

# Workflow ausfΓΌhren
act push

# Nur spezifischen Job ausfΓΌhren
act -j test

# ========== 3. Beispiele fΓΌr Deployment-Automatisierung ==========

# Vercel-Deployment
npm install -g vercel
vercel login
vercel --prod

# Netlify-Deployment
npm install -g netlify-cli
netlify login
netlify deploy --prod

# Heroku-Deployment
heroku login
git push heroku main

🎬 Zusammenfassung​

CI/CD ist ein unverzichtbares Werkzeug in der modernen Entwicklung:

  • CI: Code-Γ„nderungen automatisch testen und integrieren
  • CD: Getesteten Code automatisch deployen
  • Vorteile: Schnelles Feedback, erhΓΆhte StabilitΓ€t, gesteigerte ProduktivitΓ€t
  • Tools: GitHub Actions, Jenkins, CircleCI, etc.

Konzentrieren Sie sich auf die Entwicklung und deployen Sie schneller mit Automatisierung! πŸš€