7 Continuous Integration (CI) im GitOps-Kontext

7.1 Was ist CI in GitOps?

Continuous Integration in GitOps geht über klassische Code-Integration hinaus. CI-Pipelines bauen nicht nur die Anwendung, sondern generieren auch die Kubernetes-Manifeste und Container-Images, die später deployed werden.

Klassische CI:

Code → Build → Test → Artifact

GitOps CI:

Code → Build → Test → Container Image + K8s Manifests → Registry

7.2 Grundprinzipien

Häufige Integration
Entwickler commiten mindestens täglich. Kleine Änderungen reduzieren Merge-Konflikte und machen Probleme schneller sichtbar.

Automatisierte Builds
Jeder Commit löst automatisch einen Build aus. Keine manuellen Schritte, keine “es funktioniert auf meinem Rechner” Probleme.

Reproduzierbare Ergebnisse
Gleicher Code = gleiche Artifacts. Build-Umgebungen sind standardisiert und deterministisch.

7.3 Pipeline-Aufbau

7.3.1 Typische Pipeline-Stufen

Stufe Zweck Tools Dauer
Lint Code-Qualität prüfen ESLint, SonarQube 1-2 min
Build Artifacts erstellen npm, Maven, Go 2-5 min
Test Funktionalität validieren Jest, JUnit 5-15 min
Security Vulnerabilities finden Snyk, Trivy 2-5 min
Package Container Image bauen Docker, Buildah 3-10 min

7.4 CI-Tools

7.4.1 GitHub Actions

Direkt in GitHub integriert, einfache YAML-Konfiguration:

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

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          
      - name: Install & Test
        run: |
          npm ci
          npm test
          
      - name: Build Container
        run: |
          docker build -t myapp:${{ github.sha }} .
          docker push myregistry/myapp:${{ github.sha }}

7.4.2 Jenkins

Flexibler, aber komplexer in der Konfiguration:

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t myapp:${BUILD_NUMBER} .'
            }
        }
        stage('Test') {
            parallel {
                stage('Unit Tests') {
                    steps {
                        sh 'npm test'
                    }
                }
                stage('Security Scan') {
                    steps {
                        sh 'trivy image myapp:${BUILD_NUMBER}'
                    }
                }
            }
        }
    }
}

7.4.3 GitLab CI

YAML-basiert mit starker Docker-Integration:

stages:
  - build
  - test
  - package

build:
  stage: build
  script:
    - npm ci
    - npm run build

test:
  stage: test
  script:
    - npm test
  coverage: '/Coverage: \d+\.\d+%/'

package:
  stage: package
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  only:
    - main

7.5 Container-Image-Erstellung

7.5.1 Dockerfile-Optimierung

# Multi-stage Build für kleinere Images
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:20-alpine AS runtime
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nextjs -u 1001
WORKDIR /app
COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules
COPY --chown=nextjs:nodejs . .
USER nextjs
EXPOSE 3000
CMD ["npm", "start"]

7.5.2 Image-Tagging

# Semantische Versionierung
docker tag myapp:latest myapp:v1.2.3

# Git-Commit Hash (empfohlen für GitOps)
docker tag myapp:latest myapp:${GITHUB_SHA}

# Build-Nummer
docker tag myapp:latest myapp:build-${BUILD_NUMBER}

7.6 Testing-Strategien

7.6.1 Test-Pyramid

        E2E Tests (wenige, langsam)
      /                          \
    Integration Tests (moderate)
  /                              \
Unit Tests (viele, schnell)

Unit Tests

// Jest Beispiel
test('should calculate total price', () => {
  const items = [{ price: 10 }, { price: 20 }];
  expect(calculateTotal(items)).toBe(30);
});

Integration Tests

# API Tests mit Newman (Postman CLI)
newman run api-tests.json --environment staging.json

Contract Tests

// Pact Beispiel
const { Pact } = require('@pact-foundation/pact');

const provider = new Pact({
  consumer: 'frontend',
  provider: 'user-service'
});

7.7 Quality Gates

7.7.1 Automatische Gates

# SonarQube Quality Gate
- name: SonarCloud Scan
  uses: SonarSource/sonarcloud-github-action@master
  
- name: Check Quality Gate
  run: |
    if [ "$SONAR_QUALITY_GATE_STATUS" != "PASSED" ]; then
      echo "Quality gate failed"
      exit 1
    fi

7.7.2 Coverage-Requirements

// package.json
{
  "jest": {
    "coverageThreshold": {
      "global": {
        "branches": 80,
        "functions": 80,
        "lines": 80,
        "statements": 80
      }
    }
  }
}

7.8 Security Integration

7.8.1 Dependency Scanning

- name: Audit Dependencies
  run: npm audit --audit-level high

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

7.8.2 Container Scanning

# Trivy für Container-Vulnerabilities
trivy image --severity HIGH,CRITICAL myapp:latest

# Hadolint für Dockerfile-Qualität
hadolint Dockerfile

7.9 Artifact Management

7.9.1 Container Registry

- name: Login to Registry
  uses: docker/login-action@v3
  with:
    registry: ghcr.io
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}

- name: Push Image
  run: |
    docker push ghcr.io/myorg/myapp:${{ github.sha }}
    docker push ghcr.io/myorg/myapp:latest

7.9.2 Manifest Updates

Nach erfolgreichem Build müssen die Kubernetes-Manifeste aktualisiert werden:

# Automatisches Update der Image-Tags
sed -i "s|image: myapp:.*|image: myapp:${GITHUB_SHA}|" k8s/deployment.yaml
git add k8s/deployment.yaml
git commit -m "Update image to ${GITHUB_SHA}"
git push

7.10 Trigger-Strategien

Trigger Zweck Beispiel
Push to main Production Build Vollständige Pipeline + Deployment
Pull Request Validation Tests + Security Scan
Schedule Dependency Updates Nightly builds
Manual Hotfixes Emergency deployments
on:
  push:
    branches: [main]
    paths: ['src/**', 'Dockerfile']
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 2 * * *'  # Täglich um 2 Uhr
  workflow_dispatch:     # Manueller Trigger

7.11 Monitoring und Feedback

7.11.1 Build-Metriken

7.11.2 Notifications

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

CI in GitOps automatisiert nicht nur das Testen und Bauen von Code, sondern auch die Erstellung der Deployment-Artifacts. Wichtige Erfolgsfaktoren:

  1. Schnelle Feedback-Loops durch optimierte Pipelines
  2. Automatisierte Quality Gates für konsistente Qualität
  3. Reproduzierbare Builds für zuverlässige Deployments
  4. Security-Integration von Anfang an
  5. Klare Trigger-Strategien für verschiedene Szenarien

Eine gut konfigurierte CI-Pipeline reduziert manuelle Arbeit und macht Deployments vorhersagbar und sicher.