Design wechseln

GitHub Actions Composite Action entwickeln: Praxisleitfaden von action.yml bis Marketplace

Sie starren auf die Workflow-Logs – zum fünfzehnten Mal Fehler. Ursache? Beim npm install in einem privaten Repository fehlte wieder NODE_AUTH_TOKEN.

Das war diese Woche schon das dritte Mal. Acht Repositories, alle mit nahezu identischen Workflow-Konfigurationen: checkout, setup-node, install, build, test. Eine Änderung bedeutet acht Repositories synchron zu halten. Als Sie Node upgraden, passen Sie fünf Repos an – drei vergessen Sie.

In dem Moment wird klar: So geht es nicht weiter. GitHub Actions Composite Actions existieren genau dafür – wiederkehrende Schritte in wiederverwendbare Komponenten packen und wie Funktionen in mehreren Workflows aufrufen. Dieser Artikel führt Sie von der ersten Composite Action bis zur Marketplace-Veröffentlichung und vermittelt die Kernkompetenz für CI/CD-Komponenten.

Kapitel 1: Kernkonzepte der Composite Action

1.1 Was ist eine Composite Action?

Eine Composite Action ist GitHub Actions’ Mechanismus zur Komponentenbildung. Sie kapselt mehrere Schritte (steps) in einer eigenständigen Action, die sich in verschiedenen Workflows wiederverwenden lässt.

Anders als JavaScript Actions oder Docker Actions brauchen Composite Actions keinen Code. Sie definieren Schritte per YAML – GitHub führt sie automatisch aus. Kurz gesagt: eine Composite Action ist die „Funktions-Kapselung” einer Schrittgruppe.

Offiziell: Composite Actions werden mit runs.using: "composite" markiert; alle Schritte laufen auf demselben Runner. Sie greifen direkt auf Arbeitsverzeichnis, Umgebungsvariablen und andere Actions zu.

1.2 Die drei Action-Typen im Vergleich

GitHub Actions unterstützt drei Action-Typen:

TypUmsetzungEinsatz
JavaScript ActionJS/TS-CodeKomplexe Logik, API-Aufrufe
Docker ActionDockerfileSpezifische Umgebung, Abhängigkeiten
Composite ActionReines YAMLBestehende Schritte kombinieren, schnelle Wiederverwendung

Der Vorteil ist offensichtlich: null Code, schnelle Entwicklung, einfache Wartung. Kein Packaging, keine Kompilierung, kein Dependency-Management – nur YAML.

1.3 Composite Action vs. wiederverwendbarer Workflow

Hier verwechseln viele. Beides klingt nach „Wiederverwendung”, ist aber grundverschieden:

Composite Action ist eine Schrittgruppe. Sie läuft innerhalb eines Jobs, nutzt den Runner des Aufrufers und braucht explizite Secrets-Weitergabe.

Wiederverwendbarer Workflow ist eine komplette Pipeline. Er erzeugt einen eigenen Job, kann einen eigenen Runner haben; Secrets werden automatisch vererbt.

Beispiel: „Abhängigkeiten installieren + Tests ausführen” als Baustein → Composite Action. Den gesamten Ablauf „Build → Test → Deploy” standardisieren → wiederverwendbarer Workflow. Kapitel 4 vergleicht im Detail.

Kapitel 2: Die erste Composite Action entwickeln

2.1 action.yml im Detail

Das Herzstück ist action.yml – Metadaten mit Name, Inputs, Outputs und Ausführungsschritten.

Minimales Beispiel:

name: 'Hello World'
description: 'A simple composite action'
runs:
  using: "composite"
  steps:
    - run: echo "Hello from composite action!"
      shell: bash

Diese Action druckt nur eine Zeile. In echten Projekten brauchen Sie Parametrisierung und Outputs.

2.2 Vollständiges action.yml-Beispiel

Praxisnahe Composite Action für Build und Test in Node.js-Projekten:

name: 'Build and Test'
description: 'Install dependencies, build project, and run tests'
author: 'Your Name'

inputs:
  node-version:
    description: 'Node.js version to use'
    required: true
    default: '20'
  install-command:
    description: 'Command to install dependencies'
    required: false
    default: 'npm ci'
  build-command:
    description: 'Command to build the project'
    required: false
    default: 'npm run build'
  test-command:
    description: 'Command to run tests'
    required: false
    default: 'npm test'

outputs:
  build-path:
    description: 'Path to the build output'
    value: ${{ steps.build.outputs.path }}
  test-coverage:
    description: 'Test coverage percentage'
    value: ${{ steps.coverage.outputs.value }}

runs:
  using: "composite"
  steps:
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
        cache: 'npm'

    - name: Install dependencies
      run: ${{ inputs.install-command }}
      shell: bash

    - name: Build project
      id: build
      run: |
        ${{ inputs.build-command }}
        echo "path=dist" >> $GITHUB_OUTPUT
      shell: bash

    - name: Run tests
      id: coverage
      run: |
        ${{ inputs.test-command }}
        echo "value=85" >> $GITHUB_OUTPUT
      shell: bash

2.3 Felder im Detail

inputs: Parameter der Action. Pro Parameter möglich:

  • description: Erklärung (erscheint im Marketplace)
  • required: Pflichtfeld ja/nein
  • default: Standardwert

outputs: Rückgabewerte über die Umgebungsvariable $GITHUB_OUTPUT. Format:

echo "name=value" >> $GITHUB_OUTPUT

runs.steps: Ausführungsschritte. Ähnlich wie in normalen Workflows, mit zwei wichtigen Unterschieden:

  1. shell muss explizit gesetzt werden. Jeder run-Schritt braucht shell: bash (oder sh, pwsh) – Pflicht bei Composite Actions.

  2. uses kann andere Actions aufrufen, z. B. actions/setup-node@v4 oben.

2.4 Typische Stolpersteine

Aus der Praxis – drei häufige Fallen:

Stolperstein 1: inputs haben kein type-Feld

inputs unterstützen nur strings. Kein type: boolean oder type: number wie bei wiederverwendbaren Workflows. Boolesche Werte als "true" / "false" übergeben und im Schritt prüfen.

Stolperstein 2: shell ist Pflicht

In normalen Workflows kann run ohne shell laufen – GitHub wählt automatisch. In Composite Actions fehlt shell → Fehler.

Stolperstein 3: outputs brauchen step id

Der value-Eintrag muss auf Schritt-Outputs verweisen:

outputs:
  my-output:
    value: ${{ steps.my-step.outputs.result }}

Der Schritt braucht id:

- id: my-step
  run: echo "result=hello" >> $GITHUB_OUTPUT

Kapitel 3: Composite Actions nutzen

3.1 Lokale Referenz

Am einfachsten: dieselbe Action im Repository unter .github/actions/build-test/action.yml:

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

      # Lokale Referenz
      - uses: ./.github/actions/build-test
        with:
          node-version: '20'
          test-command: 'npm run test:ci'

Pfad beginnt mit ./, relativ zum Repository-Root. Ideal für interne Team-Wiederverwendung ohne Marketplace.

3.2 Referenz über Repositories hinweg

Für mehrere Repositories: Action in eigenem Repository ablegen und cross-repo referenzieren:

steps:
  # Shared Action der Organisation
  - uses: your-org/shared-actions/build@v1
    with:
      node-version: '18'

Format: owner/repo/path@version. path ist der relative Pfad zur Action im Repository.

Empfohlenes Design für Organisations-Action-Repos:

shared-actions/
├── build/
│   └── action.yml        # Build
├── deploy/
│   └── action.yml        # Deploy
├── lint/
│   └── action.yml        # Lint
└── README.md

Referenzen dann klar:

  • your-org/shared-actions/build@v1
  • your-org/shared-actions/deploy@v1

3.3 Nutzung aus dem Marketplace

Nach Veröffentlichung suchen und referenzieren:

steps:
  # Angenommen, Ihre Action heißt „build-test-action"
  - uses: your-org/build-test-action@v1.2.3
    with:
      node-version: '20'

Der Marketplace bietet Versionsauswahl, Nutzungsstatistiken und README-Anzeige – gut für Open Source oder öffentlich geteilte Actions.

3.4 Versionsstrategie

Drei Wege, eine Action zu pinnen:

# Variante 1: Commit-SHA (am sichersten, unveränderlich)
- uses: your-org/action@a1b2c3d4e5f6...

# Variante 2: Semantisches Version-Tag (empfohlen)
- uses: your-org/action@v1.2.3

# Variante 3: Major-Tag (folgt automatisch neuester v1.x)
- uses: your-org/action@v1

# Nicht empfohlen: latest-Tag (unerwartetes Upgrade möglich)
# - uses: your-org/action@latest

Sicherheitsempfehlungen:

Produktion: Commit-SHA – unveränderlich, kein Tag-Update durch Maintainer.

Interne Projekte: Major-Tag (z. B. @v1) – folgt v1.x mit Bugfixes und Features.

@latest vermeiden – kann Builds unbemerkt brechen.

Kapitel 4: Composite Action vs. wiederverwendbarer Workflow

4.1 Funktionsvergleich

DimensionComposite ActionWiederverwendbarer Workflow
AusführungsebeneSchrittgruppe im JobEigener Job
RunnerRunner des AufrufersNeuer Runner (oder festgelegt)
SecretsExplizite WeitergabeAutomatische Vererbung
Input-TypenNur stringboolean / number / string
Output-Weitergabe$GITHUB_OUTPUToutputs + workflow_call
ParallelitätskontrolleLimit des AufrufersUnabhängig konfigurierbar
UmgebungsvariablenVererbung + ErgänzungEigener Scope
EinsatzEinzelfunktion kapselnGanze Pipeline standardisieren

4.2 Entscheidungsmatrix

Composite Action, wenn:

  • Wiederkehrende Build-/Test-/Deploy-Schritte bündeln
  • Schritte im Job mit anderen interagieren sollen
  • Workflow flexibel bleiben soll, nur Teilschritte wiederverwendet werden
  • Secrets-Weitergabe kontrolliert und sicher sein muss

Wiederverwendbarer Workflow, wenn:

  • Die gesamte CI/CD-Pipeline standardisiert werden soll
  • Mehrere Projekte denselben End-to-End-Ablauf brauchen
  • Secrets automatisch vererbt werden sollen (weniger Konfiguration)
  • Workflow-Level-Optionen wie if, timeout-minutes nötig sind

Kombination:

Best Practice: beides zusammen. Wiederverwendbarer Workflow ruft Composite Actions auf:

# .github/workflows/ci.yml (wiederverwendbarer Workflow)
on:
  workflow_call:
    inputs:
      node-version:
        type: string
        default: '20'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      # Composite Action aufrufen
      - uses: ./.github/actions/build-test
        with:
          node-version: ${{ inputs.node-version }}

Workflow-Level-Standard plus Action-Level-Schrittwiederverwendung.

Kapitel 5: Versionsverwaltung und Veröffentlichung

5.1 Git Tags – Best Practices

Kern der Action-Veröffentlichung: semantische Version + Major-Tag:

# Semantisches Version-Tag
git tag -a v1.0.0 -m "Initial release"
git push origin v1.0.0

# Major-Tag (folgt neuester v1.x)
git tag -fa v1 -m "Update v1 tag to latest"
git push origin v1 --force

Bei v1.1.0 Major-Tag aktualisieren:

git tag -a v1.1.0 -m "Add new feature"
git push origin v1.1.0

# v1-Tag auf neueste Version zeigen
git tag -fa v1 -m "Update v1 tag to v1.1.0"
git push origin v1 --force

Nutzer wählen:

  • @v1.1.0 für feste Version
  • @v1 für automatische v1.x-Updates

5.2 Marketplace-Veröffentlichung

Voraussetzungen:

1. README.md vorbereiten

Enthält:

  • Action-Name und Beschreibung
  • Inputs und Outputs
  • Nutzungsbeispiele
  • Lizenz

2. action.yml vorbereiten

Felder name, description, author, optional branding vollständig ausfüllen.

3. Release erstellen

Im GitHub-Repository:

  1. „Releases” → „Draft a new release”
  2. Tag wählen (z. B. v1.0.0)
  3. Release Notes eintragen
  4. „Publish this Action to the GitHub Marketplace” aktivieren
  5. Veröffentlichen

GitHub validiert action.yml und listet die Action im Marketplace.

5.3 Automatisierter Release-Workflow

Workflow für automatische Releases:

name: Release Action

on:
  push:
    tags:
      - 'v*'

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

      - name: Update major tag
        run: |
          # Major-Version extrahieren
          MAJOR=$(echo $GITHUB_REF | sed 's/refs\/tags\/v\([0-9]*\).*/\1/')
          
          # Major-Tag aktualisieren
          git config user.name github-actions
          git config user.email github-actions@github.com
          git tag -fa v$MAJOR -m "Update v$MAJOR tag"
          git push origin v$MAJOR --force

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v1
        with:
          generate_release_notes: true

Bei Tag-Push: Major-Tag aktualisieren und Release anlegen.

Kapitel 6: Fortgeschrittene Techniken und Best Practices

6.1 Secrets sicher übergeben

Composite Actions lesen den secrets-Kontext nicht direkt. Explizite Weitergabe:

# Im Workflow
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: ./.github/actions/deploy
        with:
          token: ${{ secrets.DEPLOY_TOKEN }}
        env:
          AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }}
# In action.yml
inputs:
  token:
    description: 'Deploy token'
    required: true

runs:
  using: "composite"
  steps:
    - run: deploy --token ${{ inputs.token }}
      shell: bash
      env:
        AWS_ACCESS_KEY: ${{ env.AWS_ACCESS_KEY }}

Sicherheit:

  • Sensible Daten nicht über inputs (können in Logs sichtbar werden)
  • Sensible Daten über env (werden maskiert)
  • Im README klar angeben, welche Secrets nötig sind

6.2 Lokale Skripte nutzen

Komplexe Logik gehört nicht ins YAML. Skripte im Action-Verzeichnis:

.github/actions/build-test/
├── action.yml
└── scripts/
    └── build.sh

In action.yml aufrufen:

runs:
  using: "composite"
  steps:
    - run: $GITHUB_ACTION_PATH/scripts/build.sh
      shell: bash

$GITHUB_ACTION_PATH ist das Wurzelverzeichnis der Composite Action.

6.3 Organisations-Action-Repository

Für Teams: zentral verwaltete Shared Actions:

your-org/shared-actions/
├── .github/
│   └── workflows/
│       └── test.yml       # Alle Actions testen
├── build/
│   ├── action.yml
│   └── README.md
├── deploy/
│   ├── action.yml
│   └── README.md
├── lint/
│   ├── action.yml
│   └── README.md
└── README.md

Jedes Unterverzeichnis ist eine eigenständige Action mit README und Tests.

6.4 Fallen und Debugging

Falle 1: Verschachtelungstiefe

Composite Actions, die Composite Actions aufrufen: maximal 10 Ebenen. Empfehlung: höchstens 3 – tiefer wird Debugging mühsam.

Falle 2: Scope von Umgebungsvariablen

env in Composite Actions gilt nur im jeweiligen Schritt. Für Schritte übergreifend: GITHUB_ENV:

steps:
  - run: echo "MY_VAR=value" >> $GITHUB_ENV
    shell: bash
  - run: echo $MY_VAR  # Zugriff möglich
    shell: bash

Debugging:

  1. ACTIONS_STEP_DEBUG=true für ausführliche Logs
  2. echo in Schritten für Variablenausgabe
  3. tmate-Action für SSH-Debugging (nicht in Produktion)

Fazit

Composite Actions sind das zentrale Werkzeug zur Komponentenbildung in GitHub Actions – wiederholte Konfiguration entfällt, CI-Schritte lassen sich wie Funktionen kapseln.

Drei Kernpunkte:

Klare Struktur: action.yml definiert inputs/outputs/steps wie eine Funktionssignatur. Parametrisierung macht Actions flexibel, Outputs liefern Ergebnisse an Aufrufer.

Richtige Wahl: Composite Actions für Einzelfunktionen (Build, Test, Deploy); wiederverwendbare Workflows für ganze Pipelines. Kombiniert am besten.

Sichere Versionierung: Commit-SHA für Produktion, Major-Tag für interne Projekte. latest vermeiden.

Nächster Schritt: erste Composite Action im Projekt anlegen, wiederholte build-test-Schritte bündeln und im Marketplace fürs Team oder die Community veröffentlichen.

GitHub Actions Composite Action entwickeln

Von null eine wiederverwendbare Composite Action erstellen und Build-/Test-Schritte bündeln

⏱️ Estimated time: 30 min

  1. 1

    Step 1: Action-Verzeichnisstruktur anlegen

    Composite-Action-Verzeichnis im Repository erstellen:

    • mkdir -p .github/actions/build-test
    • action.yml-Datei anlegen
  2. 2

    Step 2: action.yml konfigurieren

    inputs, outputs und Ausführungsschritte definieren:

    • inputs für Parameter (node-version, test-command)
    • outputs für Rückgabewerte (build-path, coverage)
    • runs.steps erfordern explizit shell: bash
  3. 3

    Step 3: Lokal referenzieren und testen

    Im Workflow referenzieren und testen:

    • uses: ./.github/actions/build-test
    • with: node-version: '20'
    • Erst nach erfolgreichem lokalem Test veröffentlichen
  4. 4

    Step 4: Git Tags erstellen

    Semantische Version plus Major-Tag:

    • git tag -a v1.0.0 -m 'Initial release'
    • git tag -fa v1 -m 'Update v1 tag'
    • git push origin v1.0.0 v1
  5. 5

    Step 5: Im Marketplace veröffentlichen

    Über die GitHub-Oberfläche veröffentlichen:

    • Releases → Draft a new release
    • Tag wählen (z. B. v1.0.0)
    • Publish to Marketplace aktivieren
    • GitHub validiert und veröffentlicht automatisch

FAQ

Was ist der Unterschied zwischen Composite Action und wiederverwendbarem Workflow?
Eine Composite Action ist eine Schrittgruppe innerhalb eines Jobs, nutzt den Runner des Aufrufers und erfordert explizite Secrets-Weitergabe. Ein wiederverwendbarer Workflow erzeugt einen eigenen Job; Secrets werden automatisch vererbt. Composite Actions kapseln einzelne Funktionen, wiederverwendbare Workflows standardisieren ganze Pipelines.
Warum haben inputs einer Composite Action kein type-Feld?
inputs unterstützen bei Composite Actions nur den Typ string – anders als bei wiederverwendbaren Workflows, wo boolean oder number möglich sind. Für Boolesche Werte Strings wie 'true' oder 'false' übergeben und im Schritt auswerten.
Wie werden Secrets in Composite Actions übergeben?
Composite Actions können den secrets-Kontext nicht direkt lesen. Übergabe erfolgt explizit über inputs (Werte werden in Logs maskiert) oder über env (sicherer, Werte erscheinen nicht in Logs).
Commit-SHA oder Tag beim Referenzieren einer Action?
Produktion: Commit-SHA (am sichersten, unveränderlich). Interne Projekte: Major-Tag (z. B. @v1, folgt automatisch der neuesten Version). @latest vermeiden – unerwartete Upgrades können Builds brechen.
Wie tief dürfen Composite Actions verschachtelt werden?
Composite Actions, die andere Composite Actions aufrufen, sind maximal 10 Ebenen tief. Empfehlung: nicht mehr als 3 Ebenen – tiefe Verschachtelung erschwert das Debugging erheblich.
Muss shell in Composite Actions explizit gesetzt werden?
Ja. Jeder run-Schritt braucht shell: bash (oder sh, pwsh). Das ist Pflicht – in normalen Workflows kann shell entfallen, in Composite Actions nicht.

8 Min. Lesezeit · Veröffentlicht am: 6. Mai 2026 · Aktualisiert am: 9. Juli 2026

Ähnliche Beiträge

Kommentare

Melde dich mit GitHub an, um einen Kommentar zu hinterlassen

Easton BlogEaston Blog