Veröffentlicht am: 6. Juli 2026

13 Minuten Lesezeit

CI/CD Inputs: die sichere Methode zur Parameterübergabe an Pipelines

Wie CI/CD Inputs Parameter typsicher und validiert übergeben und fehleranfällige Variablen ersetzen – für verlässlichere, wartbarere Pipelines.

CI/CD Inputs: die sichere Methode zur Parameterübergabe an Pipelines

GitLab CI/CD Inputs sind eine gezielt entwickelte Methode zur Parameterübergabe in Pipelines. Als Funktion, die speziell für typisierte Parameter mit Validierung, klaren Verträgen und kontrollierter Übergabe konzipiert wurde, lösen Inputs die Probleme, um die Teams jahrelang mit Variablen herumarbeiten mussten.

CI/CD-Variablen dienten lange als Standardweg, um Parameter an Pipelines zu übergeben. Ursprünglich waren sie jedoch für das Speichern von Konfigurationswerten gedacht – nicht als ausgefeilter Mechanismus zur Parameterübergabe in komplexen Abläufen. Aus dieser Diskrepanz entstanden Zuverlässigkeitsprobleme, Sicherheitsbedenken und zusätzlicher Wartungsaufwand, die sich mit Inputs vermeiden lassen.

Dieser Artikel zeigt, warum sich CI/CD Inputs als bevorzugter Ansatz für Pipeline-Parameter eignen. Dabei wird deutlich, wie Inputs Typsicherheit schaffen, häufige Pipeline-Fehler verhindern, Namenskollisionen bei Variablen ausschließen und die Automatisierung wartbarer machen. Praktische Beispiele zeigen Inputs im Einsatz und wie sie konkrete Probleme lösen – als Anstoß, von variablenbasierten Behelfslösungen zur verlässlicheren Arbeit mit Inputs zu wechseln.

Grundlagen von CI/CD Inputs

Inputs bieten typisierte Parameter für wiederverwendbare Pipeline-Konfigurationen, mit eingebauter Validierung bei der Pipeline-Erstellung. Sie schaffen einen klaren Vertrag zwischen der einbindenden Pipeline und der Konfiguration und legen ausdrücklich fest, welche Parameter erwartet werden, welchen Typ sie haben und welchen Einschränkungen sie unterliegen.

Was Inputs besser lösen als Variablen

Damit die Vorteile von Inputs greifbar werden, lohnt ein Blick auf die Schwächen, die der variablenbasierte Ansatz mitbringt – und die Inputs gezielt beheben.

Variablen für die Parameterübergabe zu nutzen, bringt zahlreiche und mühsame Probleme mit sich.

Keine Typvalidierung

Variablen sind Zeichenketten. Es gibt keine Typvalidierung: Eine Pipeline erwartet etwa einen Boolean oder eine Zahl, erhält aber versehentlich eine Zeichenkette. Das führt zu unerwarteten Fehlern tief im Pipeline-Ablauf. Bei einem Deployment-Workflow etwa schlägt eine kritische Produktivbereitstellung fehl, weil eine Boolean-Prüfung einen Wert nicht wie erwartet erhält – und das erst weit fortgeschritten im Ablauf.

Veränderbarkeit zur Laufzeit

Variablen lassen sich während der gesamten Pipeline-Laufzeit ändern. Das erzeugt unvorhersehbares Verhalten, wenn mehrere Jobs denselben Wert zu ändern versuchen. Ein Beispiel: deploy_job_a setzt DEPLOY_ENV=staging, doch deploy_job_b ändert den Wert von DEPLOY_ENV auf production.

Sicherheitsrisiken

Sicherheitsbedenken entstehen, weil Variablen, die als einfache Parameter gedacht sind, oft dieselben Zugriffsrechte erhalten wie sensible Secrets. Es fehlt ein klarer Vertrag, der festlegt, welche Parameter eine Pipeline erwartet, welchen Typ sie haben und welche Standardwerte gelten. Ein scheinbar harmloser Parameter wie BUILD_TYPE erhält damit plötzlich Zugriff auf Produktions-Secrets – schlicht, weil Variablen von sich aus nicht zwischen Parametern und sensiblen Daten unterscheiden.

Besonders problematisch: Fehler zeigen sich zu spät im Ablauf. Eine falsch konfigurierte Variable führt unter Umständen erst tief im Pipeline-Lauf zu einem Fehler und bindet dabei CI/CD-Ressourcen. Teams entwickeln aufwendige Behelfslösungen – eigene Validierungsskripte, ausführliche Dokumentation, komplexe Namenskonventionen –, nur um die variablenbasierte Parameterübergabe halbwegs verlässlich zu machen.

Viele Nutzende haben sich lokale Debugging-Möglichkeiten gewünscht, um Pipeline-Konfigurationen vor der Bereitstellung zu testen. So naheliegend das klingt, in der Praxis scheitert es schnell: Unternehmensweite CI/CD-Abläufe binden Dutzende externe Systeme ein – Cloud-Anbieter, Artefakt-Repositorys, Security-Scanner, Deployment-Ziele –, die sich lokal kaum nachbilden lassen. Und selbst wenn, wäre der Aufwand kaum wartbar. Diese Diskrepanz führte zu einer anderen Fragestellung. Statt „Wie lassen sich Pipelines lokal testen?“ lautete die Frage nun: „Wie lassen sich Konfigurationsprobleme durch variablenbasierte Parameterübergabe verhindern, bevor eine CI/CD-Automatisierung überhaupt läuft?“

Inputs in der Praxis

Die folgenden Beispiele zeigen, wie Inputs die beschriebenen Probleme im Detail lösen – von der Variablenpräzedenz über die Typvalidierung bis zur schrittweisen Migration.

Variablenpräzedenz: das Problem

Das Variablensystem von GitLab kennt mehrere Präzedenzebenen, um verschiedene Anwendungsfälle flexibel abzudecken. Dieses System deckt viele sinnvolle Szenarien ab – etwa wenn Administratoren instanz- oder gruppenweite Standardwerte setzen, die einzelne Projekte bei Bedarf überschreiben. Beim Aufbau wiederverwendbarer Pipeline-Komponenten kann es jedoch zu Schwierigkeiten führen.

Bei Komponenten oder Templates, die über verschiedene Projekte und Gruppen hinweg genutzt werden, macht die Präzedenzhierarchie das Verhalten weniger vorhersehbar. Ein Template, das in einem Projekt einwandfrei funktioniert, verhält sich in einem anderen möglicherweise anders – wegen gruppen- oder instanzweiter Überschreibungen, die in der Pipeline-Konfiguration nicht sichtbar sind.

Werden mehrere Templates eingebunden, wird zudem schwer nachvollziehbar, welche Variablen wo gesetzt werden und wie sie zusammenwirken. Autor(inn)en von Komponenten müssen darüber hinaus nicht nur dokumentieren, welche Variablen ihr Template nutzt, sondern auch mögliche Konflikte mit Variablen höherer Präzedenz.

Beispiel zur Variablenpräzedenz

Haupt-Pipeline-Datei (.gitlab-ci.yml):

      variables:
  ENVIRONMENT: production  # Top-level default for all jobs
  DATABASE_URL: prod-db.example.com

include:
  - local: 'templates/test-template.yml'
  - local: 'templates/deploy-template.yml'

    

Test-Template (templates/test-template.yml):

      run-tests:
  variables:
    ENVIRONMENT: test  # Job-level variable overrides the default
  script:
    - echo "Running tests in $ENVIRONMENT environment"
    - echo "Database URL is $DATABASE_URL"  # Still inherits prod-db.example.com!
    - run-integration-tests --env=$ENVIRONMENT --db=$DATABASE_URL
    # Issue: Tests run in "test" environment but against production database

    

Deploy-Template (templates/deploy-template.yml):

      deploy-app:
  script:
    - echo "Deploying to $ENVIRONMENT"  # Uses production (top-level default)
    - echo "Database URL is $DATABASE_URL"  # Uses prod-db.example.com
    - deploy --target=$ENVIRONMENT --db=$DATABASE_URL
    # This will deploy to production as intended

    

Die Herausforderungen in diesem Beispiel zeigen sich an mehreren Stellen:

  1. Teilweise Vererbung: Der Test-Job erhält zwar ENVIRONMENT=test, erbt aber weiterhin DATABASE_URL=prod-db.example.com – die Tests laufen also in der Testumgebung, aber gegen die Produktionsdatenbank.
  2. Koordinationsaufwand: Template-Autor(inn)en müssen wissen, welche Top-Level-Variablen existieren und kollidieren könnten.
  3. Überschreibungsverhalten: Job-Variablen mit gleichem Namen überschreiben die Standardwerte, was nicht immer offensichtlich ist.
  4. Versteckte Abhängigkeiten: Templates werden dadurch von den Variablennamen der Haupt-Pipeline abhängig.

Flexibilität und Geltungsbereich der Konfiguration

Ein Vorteil von Inputs liegt in ihrer Flexibilität zur Konfigurationszeit. Inputs werden während der Pipeline-Erstellung ausgewertet und im Format $[[ inputs.input-id ]] interpoliert. Dadurch lassen sie sich überall in der Pipeline-Konfiguration einsetzen – in Job-Namen, in rules-Bedingungen, bei Images und in jedem anderen YAML-Element. Das hebt eine langjährige Einschränkung der Variableninterpolation in bestimmten Kontexten auf.

Ein häufiger Anwendungsfall: Job-Namen wie test-$[[ inputs.environment ]]-deployment.

Inputs in Job-Namen verhindern Namenskollisionen, wenn dieselbe Komponente mehrfach in einer Pipeline eingebunden wird. Ohne diese Möglichkeit würde die zweite Einbindung die erste überschreiben. Input-basierte Job-Namen sorgen dafür, dass jede Einbindung eindeutig benannte Jobs erzeugt.

Vorher (mit Variablen):

      test-service:
  variables:
    SERVICE_NAME: auth-service
    ENVIRONMENT: staging
  script:
    - run-tests-for $SERVICE_NAME in $ENVIRONMENT

    

Mit Inputs:

      spec:
  inputs:
    environment:
      type: string
    service_name:
      type: string

test-$[[ inputs.service_name ]]-$[[ inputs.environment ]]:
  script:
    - run-tests-for $[[ inputs.service_name ]] in $[[ inputs.environment ]]

    

Wird dies mehrfach mit unterschiedlichen Inputs eingebunden, entstehen Jobs wie test-auth-service-staging, test-payment-service-production und test-notification-service-development. Jeder Job trägt einen eindeutigen, aussagekräftigen Namen, der seinen Zweck klar erkennen lässt – die Pipeline-Visualisierung wird dadurch deutlich übersichtlicher als bei mehreren gleichnamigen Jobs, die einander überschreiben.

Angewendet auf das obige Präzedenz-Beispiel, ergibt sich mit Inputs ein unmittelbarer Vorteil: Statt mehrere Template-Dateien zu pflegen, genügt ein einziges wiederverwendbares Template mit unterschiedlichen Input-Werten.

      spec:
  inputs:
    environment:
      type: string
    database_url:
      type: string
    action:
      type: string
---
$[[ inputs.action ]]-$[[ inputs.environment ]]:
  script:
    - echo "Running $[[ inputs.action ]] in $[[ inputs.environment ]] environment"
    - echo "Database URL is $[[ inputs.database_url ]]"
    - run-$[[ inputs.action ]] --env=$[[ inputs.environment ]] --db=$[[ inputs.database_url ]]

    

In der Haupt-Datei .gitlab-ci.yml lässt sich das Template zweimal (oder öfter) mit unterschiedlichen Werten einbinden, ohne Namenskollisionen:

      include:
  - local: 'templates/environment-template.yml'
    inputs:
      environment: test
      database_url: test-db.example.com
      action: tests
  - local: 'templates/environment-template.yml'
    inputs:
      environment: production
      database_url: prod-db.example.com
      action: deploy

    

Das Ergebnis: Statt getrennter YAML-Dateien für Test- und Deployment-Jobs gibt es ein einziges wiederverwendbares Template, das beide Fälle sicher abdeckt. Der Ansatz skaliert auf beliebig viele Umgebungen oder Job-Typen, verringert den Wartungsaufwand, vermeidet Code-Duplizierung und sorgt für Konsistenz über die gesamte Pipeline-Konfiguration hinweg – ein Template statt vieler, ohne das Risiko von Variablenkollisionen oder Konfigurationsabweichungen.

Validierung und Typsicherheit

Ein weiterer zentraler Unterschied zwischen Variablen und Inputs liegt in der Validierung. Inputs unterstützen verschiedene Werttypen – Zeichenketten, Zahlen, Booleans und Arrays – und validieren sie unmittelbar bei der Pipeline-Erstellung. Wird ein Input als Boolean definiert, aber eine Zeichenkette übergeben, weist GitLab die Pipeline zurück, bevor ein einziger Job ausgeführt wird.

Der Nutzen der Typvalidierung zeigt sich an einem Beispiel.

Ohne Typvalidierung (Variablen):

      variables:
  ENABLE_TESTS: "true"  # Always a string
  MAX_RETRIES: "3"      # Always a string

deploy_job:
  script:
    - if [ "$ENABLE_TESTS" = true ]; then  # This fails!
        echo "Running tests"
      fi
    - retry_count=$((MAX_RETRIES + 1))      # String concatenation: "31"

    

Das Problem: Die Boolean-Prüfung schlägt fehl, weil die Zeichenkette "true" nicht gleich dem Boolean true ist.

Mit Typvalidierung (Inputs):

      spec:
  inputs:
    enable_tests:
      type: boolean
      default: true
    max_retries:
      type: number
      default: 3

deploy_job:
  script:
    - if [ "$[[ inputs.enable_tests ]]" = true ]; then  # Works correctly
        echo "Running tests"
      fi
    - retry_count=$(($[[ inputs.max_retries ]] + 1))    # Math works: 4

    

Der praktische Unterschied: Wird eine Pipeline mit ENABLE_TESTS = yes statt true ausgelöst, bemerkt der variablenbasierte Ablauf das erst, wenn der Deployment-Job startet – und die Boolean-Auswertung im Skript fehlschlägt. Mit typisierten Inputs meldet GitLab CI/CD den Typkonflikt dagegen sofort und mit einer klaren Fehlermeldung, bevor die Pipeline überhaupt startet. Der Fehler wird an der Wurzel abgefangen statt tief im Ablauf.

Sicherheit und Zugriffskontrolle

Inputs erhöhen die Sicherheit durch kontrollierte Parameterübergabe mit ausdrücklichen Verträgen, die genau festlegen, welche Werte erwartet und zugelassen sind. Zudem sind Inputs unveränderlich: Sobald die Pipeline startet, lassen sie sich während der Ausführung nicht mehr ändern. Das sorgt für vorhersehbares Verhalten über den gesamten Pipeline-Lebenszyklus und schließt die Risiken aus, die aus der Manipulation von Variablen zur Laufzeit entstehen.

Geltungsbereich und Lebenszyklus

Werden Variablen über das Schlüsselwort variables: auf oberster Ebene der .gitlab-ci.yml definiert, gelten sie als Standard für alle Jobs der gesamten Pipeline. Beim Einbinden von Templates ist deshalb zu bedenken, welche Variablen global definiert sind, da sie über die Präzedenzordnung mit dem erwarteten Verhalten des Templates zusammenwirken können.

Inputs werden dagegen in CI-Konfigurationsdateien definiert – etwa in Komponenten oder Templates – und beim Auslösen einer Pipeline mit Werten belegt. Sie existieren ausschließlich für die Pipeline-Erstellung und -Konfiguration, sind auf die CI-Konfigurationsdatei beschränkt, in der sie definiert werden, und werden mit Beginn der Ausführung zu unveränderlichen Referenzen. Da jede Komponente ihre eigenen Inputs führt, besteht kein Risiko, dass Inputs andere Komponenten oder Templates beeinflussen – Variablenkollisionen und Überschreibungen entfallen.

Variablen und Inputs zusammen nutzen

Teams haben viel in ihre variablenbasierten Abläufe investiert, und der Umstieg auf Inputs geschieht nicht über Nacht. Deshalb gibt es Möglichkeiten, Inputs und Variablen zusammenwirken zu lassen – als Brücke zwischen bestehenden Variablen und den Vorteilen von Inputs, die zugleich zentrale Grenzen der Variablenexpansion überwindet.

Ein praxisnahes Beispiel dazu.

Variablenexpansion in rules-Bedingungen

Eine häufige Hürde entsteht, wenn Variablen, die weitere Variablenreferenzen enthalten, in rules:if-Bedingungen verwendet werden. GitLab expandiert Variablen bei der Regelauswertung nur eine Ebene tief, was zu unerwartetem Verhalten führen kann:

      # This doesn't work as expected
variables:
  TARGET_ENV:
    value: "${CI_COMMIT_REF_SLUG}"

deploy-job:
  rules:
    - if: '$TARGET_ENV == "production"'  # Compares "${CI_COMMIT_REF_SLUG}" != "production"
      variables:
        DEPLOY_MODE: "blue-green"

    

Die Funktion expand_vars löst dies, indem sie in Inputs eine vollständige Variablenexpansion erzwingt:

      spec:
  inputs:
    target_environment:
      description: "Target deployment environment"
      default: "${CI_COMMIT_REF_SLUG}"
---
deploy-job:
  rules:
    - if: '"$[[ inputs.target_environment | expand_vars ]]" == "production"'
      variables:
        DEPLOY_MODE: "blue-green"
        APPROVAL_REQUIRED: "true"
    - when: always
      variables:
        DEPLOY_MODE: "rolling"
        APPROVAL_REQUIRED: "false"
  script:
    - echo "Target: $[[ inputs.target_environment | expand_vars ]]"
    - echo "Deploy mode: ${DEPLOY_MODE}"

    

Warum das zählt

Ohne expand_vars werten Regelbedingungen die wörtliche Variablenreferenz aus (etwa "${CI_COMMIT_REF_SLUG}") statt des expandierten Werts (etwa "production"). Das führt zu Regeln, die entgegen der Erwartung nie zutreffen, und bricht die bedingte Pipeline-Logik.

Wichtige Hinweise zu expand_vars:

  • Unterstützt werden nur Variablen, die sich mit dem Schlüsselwort include verwenden lassen.
  • Die Variablen dürfen nicht maskiert (nicht als protected/masked markiert) sein.
  • Verschachtelte Variablenexpansion wird nicht unterstützt.
  • Regelbedingungen mit expand_vars müssen korrekt in Anführungszeichen gesetzt werden: '"$[[ inputs.name | expand_vars ]]" == "value"'.

Dieses Muster löst die Beschränkung auf einstufige Variablenexpansion und funktioniert für jede bedingte Logik, die vollständig aufgelöste Variablenwerte vergleicht.

Funktionsverkettung für fortgeschrittene Verarbeitung

Neben expand_vars lassen sich Funktionen wie truncate nutzen, um Werte für Namensbeschränkungen zu kürzen (etwa für Kubernetes-Ressourcennamen). So entstehen anspruchsvolle Verarbeitungsketten für Parameter, während Inputs sicher und vorhersehbar bleiben.

      spec:
  inputs:
    service_identifier:
      default: 'service-$CI_PROJECT_NAME-$CI_COMMIT_REF_SLUG'
---
create-resource:
  script:
    - resource_name=$[[ inputs.service_identifier | expand_vars | truncate(0,50) ]]

    

Diese Integrationsmöglichkeit erlaubt es, Inputs schrittweise einzuführen und dabei die bestehende Variableninfrastruktur weiter zu nutzen – der Migrationsweg wird dadurch deutlich sanfter.

Von reinen Komponenten zu vollständigen Pipelines

Bis GitLab 17.11 ließen sich Inputs nur in Komponenten und Templates über die include:-Syntax verwenden. Das beschränkte ihren Einsatz auf wiederverwendbare CI/CD-Konfigurationen und deckte den umfassenderen Bedarf an dynamischer Pipeline-Anpassung nicht ab.

Pipeline-weite Unterstützung für Inputs

Seit GitLab 17.11 lassen sich Inputs über alle Ausführungskontexte hinweg einsetzen, um das Pipeline-Verhalten sicher anzupassen, und ersetzen damit die bisherige Abhängigkeit von Pipeline-Variablen. Diese erweiterte Unterstützung umfasst:

  • Geplante Pipelines: Inputs mit Standardwerten für automatisierte Läufe definieren und bei Bedarf manuell überschreiben.
  • Nachgelagerte Pipelines: Strukturierte Inputs mit Validierung und Typsicherheit an Child- und Multi-Projekt-Pipelines übergeben.
  • Manuelle Pipelines: Nutzenden ein sauberes, validiertes Formular bereitstellen.

Diese Erweiterungen – weitere folgen – erlauben es Teams, ihre Pipelines schrittweise zu modernisieren und dabei die Abwärtskompatibilität zu wahren. Sobald Inputs vollständig eingeführt sind, lassen sich Pipeline-Variablen deaktivieren, was eine sicherere und vorhersehbarere CI/CD-Umgebung schafft.

Zusammenfassung

Der Wechsel von Variablen zu Inputs ist mehr als eine technische Umstellung – er verschiebt den Schwerpunkt hin zu wartbareren, vorhersehbareren und sichereren CI/CD-Pipelines. Variablen erfüllen weiterhin wichtige Zwecke bei der Konfiguration; Inputs liefern die Fähigkeiten zur Parameterübergabe, um die Teams jahrelang herumarbeiten mussten.

Da Variablen tief in bestehenden Abläufen verankert sind, gibt es Brücken zwischen beiden Systemen. Die Funktion expand_vars und weitere Input-Fähigkeiten erlauben eine schrittweise Einführung, ohne die bestehende Variableninfrastruktur aufzugeben.

Wer mit neuen Komponenten und Templates beginnt und dann nach und nach wichtige Abläufe migriert, erkennt rasch den Nutzen: klarere Verträge, frühere Fehlererkennung und verlässlichere Automatisierung, die organisationsweit skaliert. Der Umstieg auf Inputs schafft zudem eine gute Grundlage für den CI/CD-Katalog von GitLab, in dem wiederverwendbare Komponenten mit typisierten Schnittstellen zu wirkungsvollen Bausteinen für DevOps-Abläufe werden.

Weiterführend

Feedback erwünscht

Hat dir dieser Blogbeitrag gefallen? Hast du Fragen oder Feedback? Erstelle ein neues Diskussionsthema im GitLab-Community-Forum und lass andere an deinen Eindrücken teilhaben.

Feedback teilen

Beginne noch heute, schneller zu entwickeln

Entdecke, was dein Team mit der intelligenten Orchestrierungsplattform für DevSecOps erreichen kann.