27 Das Gesamtbild – badge-gen in der Praxis

Die vorherigen Kapitel haben GitHub Actions Stück für Stück aufgebaut: Workflows, Jobs, Secrets, Caching, Wiederverwendbarkeit, Deployment. Dieses Kapitel zeigt, wie alle Teile zusammenspielen. Am Ende steht ein vollständiges, produktionsreifes Repository mit allen Workflows, die ein Python-Projekt braucht.

27.1 Die vollständige Repository-Struktur

Nach sieben Kapiteln sieht das badge-gen Repository so aus:

badge-gen/
├── .github/
│   ├── workflows/
│   │   ├── ci.yml                    # Kontinuierliche Integration
│   │   ├── release.yml               # Versionierung und Changelog
│   │   ├── publish.yml               # PyPI-Veröffentlichung
│   │   └── pages.yml                 # GitHub Pages Deployment
│   ├── actions/
│   │   └── setup-python-env/
│   │       └── action.yml            # Lokale Composite Action
│   ├── dependabot.yml                # Automatische Updates
│   └── CODEOWNERS                    # Review-Zuständigkeiten
├── src/
│   └── badge_gen/
│       ├── __init__.py
│       ├── cli.py                    # Command-Line Interface
│       ├── generator.py              # SVG-Generierung
│       └── metrics.py                # Metrik-Sammlung
├── tests/
│   ├── __init__.py
│   ├── test_cli.py
│   ├── test_generator.py
│   └── test_metrics.py
├── pyproject.toml                    # Projekt-Konfiguration
├── README.md
├── CHANGELOG.md                      # Automatisch generiert
└── LICENSE

27.2 Die vier Workflows im Detail

27.2.1 1. CI-Workflow – die Qualitätssicherung

Dieser Workflow läuft bei jedem Push und Pull Request. Er stellt sicher, dass der Code funktioniert, bevor er gemerged wird.

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

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

permissions:
  contents: read

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install linters
        run: pip install ruff mypy

      - name: Ruff
        run: ruff check src/ tests/

      - name: Mypy
        run: mypy src/ --ignore-missing-imports

  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        python-version: ['3.10', '3.11', '3.12']
        os: [ubuntu-latest, macos-latest, windows-latest]

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
          cache: 'pip'

      - name: Install dependencies
        run: pip install -e .[dev]

      - name: Run tests
        run: pytest --cov=src/badge_gen --cov-report=xml

      - name: Upload coverage
        if: matrix.python-version == '3.12' && matrix.os == 'ubuntu-latest'
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: coverage.xml

  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install security tools
        run: pip install bandit safety

      - name: Bandit
        run: bandit -r src/ -ll

      - name: Safety
        run: pip install -e . && safety check

Was passiert: Drei parallele Jobs prüfen Code-Qualität, Funktionalität und Sicherheit. Die Test-Matrix deckt 9 Kombinationen ab (3 Python-Versionen × 3 Betriebssysteme).

27.2.2 2. Release-Workflow – Versionierung und Changelog

Dieser Workflow läuft bei Pushes auf main und erstellt automatisch neue Versionen basierend auf Conventional Commits.

# .github/workflows/release.yml
name: Release

on:
  push:
    branches: [main]

permissions:
  contents: write

jobs:
  release:
    runs-on: ubuntu-latest
    outputs:
      skipped: ${{ steps.changelog.outputs.skipped }}
      tag: ${{ steps.changelog.outputs.tag }}

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Conventional Changelog
        id: changelog
        uses: TriPSs/conventional-changelog-action@v5
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          version-file: pyproject.toml
          version-path: project.version
          skip-on-empty: 'true'
          git-push: 'true'

      - name: Create GitHub Release
        if: ${{ steps.changelog.outputs.skipped == 'false' }}
        uses: ncipollo/release-action@v1
        with:
          tag: ${{ steps.changelog.outputs.tag }}
          body: ${{ steps.changelog.outputs.clean_changelog }}

Was passiert: Der Workflow analysiert Commit-Messages seit dem letzten Tag. Bei feat: erhöht er die Minor-Version, bei fix: die Patch-Version, bei BREAKING CHANGE die Major-Version. CHANGELOG.md wird aktualisiert, ein Tag erstellt und ein GitHub Release veröffentlicht.

27.2.3 3. Publish-Workflow – PyPI-Veröffentlichung

Dieser Workflow wird durch neue Releases getriggert und veröffentlicht das Paket auf PyPI.

# .github/workflows/publish.yml
name: Publish to PyPI

on:
  release:
    types: [published]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install build tools
        run: pip install build

      - name: Build
        run: python -m build

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/

  test-install:
    needs: build
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ['3.10', '3.11', '3.12']
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: dist
          path: dist/

      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install from wheel
        run: pip install dist/*.whl

      - name: Verify installation
        run: badge-gen --version

  publish:
    needs: test-install
    runs-on: ubuntu-latest
    environment:
      name: pypi
      url: https://pypi.org/project/badge-gen/
    permissions:
      id-token: write
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: dist
          path: dist/

      - uses: pypa/gh-action-pypi-publish@release/v1

Was passiert: Der Workflow baut das Paket, testet die Installation auf verschiedenen Python-Versionen und veröffentlicht dann via Trusted Publishing auf PyPI. Das pypi Environment erfordert manuelle Genehmigung.

27.2.4 4. Pages-Workflow – Badge-Showcase

Dieser Workflow läuft bei Pushes auf main und deployed generierte Badges auf GitHub Pages.

# .github/workflows/pages.yml
name: GitHub Pages

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: pages
  cancel-in-progress: false

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
          cache: 'pip'

      - name: Install badge-gen
        run: pip install -e .

      - name: Generate badges
        run: |
          mkdir -p _site/badges
          badge-gen create --name "build" --value "passing" --color "brightgreen" -o _site/badges/build.svg
          badge-gen create --name "coverage" --value "87%" --color "yellow" -o _site/badges/coverage.svg
          badge-gen create --name "license" --value "MIT" --color "blue" -o _site/badges/license.svg
          badge-gen create --name "python" --value "3.10 | 3.11 | 3.12" --color "blue" -o _site/badges/python.svg

      - name: Generate index
        run: |
          cat > _site/index.html << 'EOF'
          <!DOCTYPE html>
          <html lang="en">
          <head>
            <meta charset="UTF-8">
            <title>badge-gen Showcase</title>
            <style>
              body { font-family: system-ui; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
              h1 { color: #333; }
              .badge { margin: 0.5rem 0; }
              code { background: #f4f4f4; padding: 0.2rem 0.4rem; border-radius: 3px; }
            </style>
          </head>
          <body>
            <h1>badge-gen Showcase</h1>
            <p>Diese Badges wurden automatisch generiert.</p>

            <h2>Verfügbare Badges</h2>
            <div class="badge"><img src="badges/build.svg" alt="Build"></div>
            <div class="badge"><img src="badges/coverage.svg" alt="Coverage"></div>
            <div class="badge"><img src="badges/license.svg" alt="License"></div>
            <div class="badge"><img src="badges/python.svg" alt="Python"></div>

            <h2>Verwendung</h2>
            <pre><code>pip install badge-gen
          badge-gen create --name "status" --value "online" --color "green"</code></pre>
          </body>
          </html>
          EOF

      - uses: actions/configure-pages@v5

      - uses: actions/upload-pages-artifact@v3
        with:
          path: _site

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - id: deployment
        uses: actions/deploy-pages@v4

Was passiert: Der Workflow installiert badge-gen aus dem aktuellen Repository, generiert Beispiel-Badges und deployed sie auf GitHub Pages.

27.3 Wie die Workflows zusammenspielen

27.3.1 Der typische Entwickler-Workflow

Tag 1: Feature entwickeln

# Neuen Branch erstellen
git checkout -b feature/add-gradient-badges

# Code schreiben, testen
# ...

# Commit mit Conventional Commits
git add .
git commit -m "feat: add gradient background support"

# Push löst CI aus
git push origin feature/add-gradient-badges

Tag 2: Pull Request

  1. PR erstellen auf GitHub
  2. CI läuft automatisch (Lint, Test, Security)
  3. Code Review durch Kollegen
  4. Merge nach Approval

Automatisch nach Merge:

  1. CI läuft erneut auf main
  2. Release Workflow erkennt feat: Commit → Version 1.3.0 → Tag → GitHub Release
  3. Pages Workflow aktualisiert die Badge-Showcase-Seite
  4. Publish Workflow wird durch das Release getriggert → Wartet auf Approval → PyPI

Ergebnis: Ein Commit-Message wie feat: add gradient background support führt automatisch zu einer neuen Version auf PyPI und aktualisierten Badges auf GitHub Pages.

27.4 Unterstützende Konfigurationen

27.4.1 Dependabot – Automatische Updates

# .github/dependabot.yml
version: 2
updates:
  # Python Dependencies
  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"
    commit-message:
      prefix: "deps"
    labels:
      - "dependencies"

  # GitHub Actions
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    commit-message:
      prefix: "ci"
    labels:
      - "ci"

Was passiert: Dependabot erstellt wöchentlich PRs für veraltete Dependencies – sowohl Python-Pakete als auch Actions. Die PRs durchlaufen automatisch den CI-Workflow.

27.4.2 CODEOWNERS – Review-Zuständigkeiten

# .github/CODEOWNERS
# Diese Datei definiert, wer Reviews für welche Dateien durchführen muss

# Workflow-Änderungen brauchen DevOps-Review
.github/workflows/    @my-org/devops-team

# Python-Code braucht Maintainer-Review
src/                  @my-org/maintainers
tests/                @my-org/maintainers

# Dokumentation kann jeder reviewen
*.md                  @my-org/contributors

27.4.3 Environment-Konfiguration

Repository Settings → Environments:

Environment Protection Rules Secrets
github-pages Deployment branches: main
pypi Required reviewers: 1, Deployment branches: main – (Trusted Publishing)
testpypi Deployment branches: main, develop – (Trusted Publishing)

27.5 Checkliste für neue Projekte

Beim Start eines neuen Projekts mit GitHub Actions:

27.5.1 Phase 1: Repository Setup

27.5.2 Phase 2: CI-Workflow

27.5.3 Phase 3: Release-Automatisierung

27.5.4 Phase 4: Deployment

27.5.5 Phase 5: Wartung

27.6 Wartung und Monitoring

27.6.1 Workflow-Laufzeiten überwachen

GitHub zeigt Laufzeiten im Actions-Tab. Bei Problemen:

Repository → Actions → [Workflow] → Workflow runs

Typische Warnsignale:

27.6.2 Billing im Blick behalten

Organization → Settings → Billing → Actions

Kostenoptimierung:

27.6.3 Benachrichtigungen einrichten

GitHub-native:

Settings → Notifications → Actions → "Send notifications for workflow runs on watched repositories"

Slack-Integration:

- name: Notify on failure
  if: failure()
  uses: slackapi/slack-github-action@v1
  with:
    channel-id: 'builds'
    slack-message: "❌ ${{ github.workflow }} failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
  env:
    SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

27.6.4 Regelmäßige Wartungsaufgaben

Aufgabe Frequenz Wie
Dependabot-PRs reviewen Wöchentlich PRs mit Label dependencies
Action-Versionen prüfen Monatlich SHA-Pinning aktualisieren
Workflow-Laufzeiten prüfen Monatlich Actions-Tab analysieren
Unused Secrets aufräumen Quartalsweise Settings → Secrets
Environment-Konfiguration prüfen Quartalsweise Settings → Environments

27.7 Typische Probleme im Alltag

27.7.1 “CI ist grün, aber lokal schlägt’s fehl”

Ursache: Unterschiedliche Umgebungen.

Lösung: act für lokale Tests nutzen (siehe Kapitel 4) oder CI-Umgebung genau dokumentieren.

27.7.2 “Der Workflow läuft nicht”

Checkliste:

  1. Workflow-Datei in .github/workflows/?
  2. YAML-Syntax korrekt? (actionlint nutzen)
  3. Trigger-Bedingung erfüllt? (on: prüfen)
  4. Branch-Filter korrekt?
  5. paths / paths-ignore blockiert?

27.7.3 “Secrets sind leer”

Checkliste:

  1. Secret existiert? (Settings → Secrets)
  2. Schreibweise korrekt? (case-sensitive)
  3. Environment-Secret aber kein Environment im Job?
  4. Forked PR? (Secrets nicht verfügbar für Forks)

27.7.4 “Caching funktioniert nicht”

Checkliste:

  1. Key ist identisch zwischen Runs?
  2. hashFiles() findet die Datei?
  3. Cache-Limit (10 GB) erreicht?
  4. Pfad existiert zum Zeitpunkt des Cachings?

27.7.5 “Deployment wartet ewig”

Checkliste:

  1. Required Reviewers konfiguriert → Genehmigung nötig
  2. Wait Timer aktiv → Wartezeit abwarten
  3. Branch nicht in Deployment Branches → falscher Branch
  4. Custom Protection Rule antwortet nicht → externe Integration prüfen

27.8 Das fertige Bild

Nach diesem Kapitel haben wir ein vollständiges CI/CD-Setup:

Was wir erreicht haben:

Ein Developer muss nur noch gute Commits schreiben – der Rest passiert automatisch.