[{"data":1,"prerenderedAt":2385},["ShallowReactive",2],{"/de-de/blog/ci-cd-inputs-secure-and-preferred-method-to-pass-parameters-to-a-pipeline":3,"navigation-de-de":1605,"banner-de-de":2036,"footer-de-de":2044,"blog-post-authors-de-de-Dov Hershkovitch":2285,"blog-related-posts-de-de-ci-cd-inputs-secure-and-preferred-method-to-pass-parameters-to-a-pipeline":2300,"blog-promotions-de-de":2323,"next-steps-de-de":2375},{"id":4,"title":5,"authors":6,"body":8,"category":1586,"date":1587,"description":1588,"extension":1589,"externalUrl":1590,"faq":1590,"featured":1591,"heroImage":1592,"meta":1593,"navigation":195,"path":1594,"seo":1595,"slug":1598,"stem":1599,"tags":1600,"template":1603,"updatedDate":1590,"__hash__":1604},"blogPosts/de-de/blog/ci-cd-inputs-secure-and-preferred-method-to-pass-parameters-to-a-pipeline.md","CI/CD Inputs: die sichere Methode zur Parameterübergabe an Pipelines",[7],"Dov Hershkovitch",{"type":9,"value":10,"toc":1567},"minimark",[11,15,19,22,25,30,33,37,40,43,49,52,57,81,86,93,96,99,103,106,111,121,124,127,132,141,231,239,309,317,366,369,405,409,420,426,429,434,484,489,566,581,584,689,695,796,799,803,806,809,814,898,908,913,1027,1037,1041,1044,1048,1058,1061,1065,1068,1071,1079,1086,1169,1176,1339,1343,1357,1365,1389,1392,1396,1406,1463,1466,1470,1477,1481,1484,1504,1507,1511,1514,1520,1529,1533,1563],[12,13,5],"h1",{"id":14},"cicd-inputs-die-sichere-methode-zur-parameterübergabe-an-pipelines",[16,17,18],"p",{},"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.",[16,20,21],{},"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.",[16,23,24],{},"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.",[26,27,29],"h2",{"id":28},"grundlagen-von-cicd-inputs","Grundlagen von CI/CD Inputs",[16,31,32],{},"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.",[26,34,36],{"id":35},"was-inputs-besser-lösen-als-variablen","Was Inputs besser lösen als Variablen",[16,38,39],{},"Damit die Vorteile von Inputs greifbar werden, lohnt ein Blick auf die Schwächen, die der variablenbasierte Ansatz mitbringt – und die Inputs gezielt beheben.",[16,41,42],{},"Variablen für die Parameterübergabe zu nutzen, bringt zahlreiche und mühsame Probleme mit sich.",[16,44,45],{},[46,47,48],"strong",{},"Keine Typvalidierung",[16,50,51],{},"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.",[16,53,54],{},[46,55,56],{},"Veränderbarkeit zur Laufzeit",[16,58,59,60,64,65,68,69,72,73,76,77,80],{},"Variablen lassen sich während der gesamten Pipeline-Laufzeit ändern. Das erzeugt unvorhersehbares Verhalten, wenn mehrere Jobs denselben Wert zu ändern versuchen. Ein Beispiel: ",[61,62,63],"code",{},"deploy_job_a"," setzt ",[61,66,67],{},"DEPLOY_ENV=staging",", doch ",[61,70,71],{},"deploy_job_b"," ändert den Wert von ",[61,74,75],{},"DEPLOY_ENV"," auf ",[61,78,79],{},"production",".",[16,82,83],{},[46,84,85],{},"Sicherheitsrisiken",[16,87,88,89,92],{},"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 ",[61,90,91],{},"BUILD_TYPE"," erhält damit plötzlich Zugriff auf Produktions-Secrets – schlicht, weil Variablen von sich aus nicht zwischen Parametern und sensiblen Daten unterscheiden.",[16,94,95],{},"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.",[16,97,98],{},"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?“",[26,100,102],{"id":101},"inputs-in-der-praxis","Inputs in der Praxis",[16,104,105],{},"Die folgenden Beispiele zeigen, wie Inputs die beschriebenen Probleme im Detail lösen – von der Variablenpräzedenz über die Typvalidierung bis zur schrittweisen Migration.",[107,108,110],"h3",{"id":109},"variablenpräzedenz-das-problem","Variablenpräzedenz: das Problem",[16,112,113,114,120],{},"Das Variablensystem von GitLab kennt mehrere ",[115,116,119],"a",{"href":117,"rel":118},"https://docs.gitlab.com/ci/variables/#cicd-variable-precedence",[],"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.",[16,122,123],{},"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.",[16,125,126],{},"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.",[128,129,131],"h4",{"id":130},"beispiel-zur-variablenpräzedenz","Beispiel zur Variablenpräzedenz",[16,133,134],{},[46,135,136,137,140],{},"Haupt-Pipeline-Datei (",[61,138,139],{},".gitlab-ci.yml","):",[142,143,148],"pre",{"className":144,"code":145,"language":146,"meta":147,"style":147},"language-yaml shiki shiki-themes github-light","variables:\n  ENVIRONMENT: production  # Top-level default for all jobs\n  DATABASE_URL: prod-db.example.com\n\ninclude:\n  - local: 'templates/test-template.yml'\n  - local: 'templates/deploy-template.yml'\n","yaml","",[61,149,150,163,179,190,197,205,219],{"__ignoreMap":147},[151,152,155,159],"span",{"class":153,"line":154},"line",1,[151,156,158],{"class":157},"shJU0","variables",[151,160,162],{"class":161},"sgsFI",":\n",[151,164,166,169,172,175],{"class":153,"line":165},2,[151,167,168],{"class":157},"  ENVIRONMENT",[151,170,171],{"class":161},": ",[151,173,79],{"class":174},"sYBdl",[151,176,178],{"class":177},"sAwPA","  # Top-level default for all jobs\n",[151,180,182,185,187],{"class":153,"line":181},3,[151,183,184],{"class":157},"  DATABASE_URL",[151,186,171],{"class":161},[151,188,189],{"class":174},"prod-db.example.com\n",[151,191,193],{"class":153,"line":192},4,[151,194,196],{"emptyLinePlaceholder":195},true,"\n",[151,198,200,203],{"class":153,"line":199},5,[151,201,202],{"class":157},"include",[151,204,162],{"class":161},[151,206,208,211,214,216],{"class":153,"line":207},6,[151,209,210],{"class":161},"  - ",[151,212,213],{"class":157},"local",[151,215,171],{"class":161},[151,217,218],{"class":174},"'templates/test-template.yml'\n",[151,220,222,224,226,228],{"class":153,"line":221},7,[151,223,210],{"class":161},[151,225,213],{"class":157},[151,227,171],{"class":161},[151,229,230],{"class":174},"'templates/deploy-template.yml'\n",[16,232,233],{},[46,234,235,236,140],{},"Test-Template (",[61,237,238],{},"templates/test-template.yml",[142,240,242],{"className":144,"code":241,"language":146,"meta":147,"style":147},"run-tests:\n  variables:\n    ENVIRONMENT: test  # Job-level variable overrides the default\n  script:\n    - echo \"Running tests in $ENVIRONMENT environment\"\n    - echo \"Database URL is $DATABASE_URL\"  # Still inherits prod-db.example.com!\n    - run-integration-tests --env=$ENVIRONMENT --db=$DATABASE_URL\n    # Issue: Tests run in \"test\" environment but against production database\n",[61,243,244,251,258,271,278,286,296,303],{"__ignoreMap":147},[151,245,246,249],{"class":153,"line":154},[151,247,248],{"class":157},"run-tests",[151,250,162],{"class":161},[151,252,253,256],{"class":153,"line":165},[151,254,255],{"class":157},"  variables",[151,257,162],{"class":161},[151,259,260,263,265,268],{"class":153,"line":181},[151,261,262],{"class":157},"    ENVIRONMENT",[151,264,171],{"class":161},[151,266,267],{"class":174},"test",[151,269,270],{"class":177},"  # Job-level variable overrides the default\n",[151,272,273,276],{"class":153,"line":192},[151,274,275],{"class":157},"  script",[151,277,162],{"class":161},[151,279,280,283],{"class":153,"line":199},[151,281,282],{"class":161},"    - ",[151,284,285],{"class":174},"echo \"Running tests in $ENVIRONMENT environment\"\n",[151,287,288,290,293],{"class":153,"line":207},[151,289,282],{"class":161},[151,291,292],{"class":174},"echo \"Database URL is $DATABASE_URL\"",[151,294,295],{"class":177},"  # Still inherits prod-db.example.com!\n",[151,297,298,300],{"class":153,"line":221},[151,299,282],{"class":161},[151,301,302],{"class":174},"run-integration-tests --env=$ENVIRONMENT --db=$DATABASE_URL\n",[151,304,306],{"class":153,"line":305},8,[151,307,308],{"class":177},"    # Issue: Tests run in \"test\" environment but against production database\n",[16,310,311],{},[46,312,313,314,140],{},"Deploy-Template (",[61,315,316],{},"templates/deploy-template.yml",[142,318,320],{"className":144,"code":319,"language":146,"meta":147,"style":147},"deploy-app:\n  script:\n    - echo \"Deploying to $ENVIRONMENT\"  # Uses production (top-level default)\n    - echo \"Database URL is $DATABASE_URL\"  # Uses prod-db.example.com\n    - deploy --target=$ENVIRONMENT --db=$DATABASE_URL\n    # This will deploy to production as intended\n",[61,321,322,329,335,345,354,361],{"__ignoreMap":147},[151,323,324,327],{"class":153,"line":154},[151,325,326],{"class":157},"deploy-app",[151,328,162],{"class":161},[151,330,331,333],{"class":153,"line":165},[151,332,275],{"class":157},[151,334,162],{"class":161},[151,336,337,339,342],{"class":153,"line":181},[151,338,282],{"class":161},[151,340,341],{"class":174},"echo \"Deploying to $ENVIRONMENT\"",[151,343,344],{"class":177},"  # Uses production (top-level default)\n",[151,346,347,349,351],{"class":153,"line":192},[151,348,282],{"class":161},[151,350,292],{"class":174},[151,352,353],{"class":177},"  # Uses prod-db.example.com\n",[151,355,356,358],{"class":153,"line":199},[151,357,282],{"class":161},[151,359,360],{"class":174},"deploy --target=$ENVIRONMENT --db=$DATABASE_URL\n",[151,362,363],{"class":153,"line":207},[151,364,365],{"class":177},"    # This will deploy to production as intended\n",[16,367,368],{},"Die Herausforderungen in diesem Beispiel zeigen sich an mehreren Stellen:",[370,371,372,387,393,399],"ol",{},[373,374,375,378,379,382,383,386],"li",{},[46,376,377],{},"Teilweise Vererbung:"," Der Test-Job erhält zwar ",[61,380,381],{},"ENVIRONMENT=test",", erbt aber weiterhin ",[61,384,385],{},"DATABASE_URL=prod-db.example.com"," – die Tests laufen also in der Testumgebung, aber gegen die Produktionsdatenbank.",[373,388,389,392],{},[46,390,391],{},"Koordinationsaufwand:"," Template-Autor(inn)en müssen wissen, welche Top-Level-Variablen existieren und kollidieren könnten.",[373,394,395,398],{},[46,396,397],{},"Überschreibungsverhalten:"," Job-Variablen mit gleichem Namen überschreiben die Standardwerte, was nicht immer offensichtlich ist.",[373,400,401,404],{},[46,402,403],{},"Versteckte Abhängigkeiten:"," Templates werden dadurch von den Variablennamen der Haupt-Pipeline abhängig.",[107,406,408],{"id":407},"flexibilität-und-geltungsbereich-der-konfiguration","Flexibilität und Geltungsbereich der Konfiguration",[16,410,411,412,415,416,419],{},"Ein Vorteil von Inputs liegt in ihrer Flexibilität zur Konfigurationszeit. Inputs werden während der Pipeline-Erstellung ausgewertet und im Format ",[61,413,414],{},"$[[ inputs.input-id ]]"," interpoliert. Dadurch lassen sie sich überall in der Pipeline-Konfiguration einsetzen – in Job-Namen, in ",[61,417,418],{},"rules","-Bedingungen, bei Images und in jedem anderen YAML-Element. Das hebt eine langjährige Einschränkung der Variableninterpolation in bestimmten Kontexten auf.",[16,421,422,423,80],{},"Ein häufiger Anwendungsfall: Job-Namen wie ",[61,424,425],{},"test-$[[ inputs.environment ]]-deployment",[16,427,428],{},"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.",[16,430,431],{},[46,432,433],{},"Vorher (mit Variablen):",[142,435,437],{"className":144,"code":436,"language":146,"meta":147,"style":147},"test-service:\n  variables:\n    SERVICE_NAME: auth-service\n    ENVIRONMENT: staging\n  script:\n    - run-tests-for $SERVICE_NAME in $ENVIRONMENT\n",[61,438,439,446,452,462,471,477],{"__ignoreMap":147},[151,440,441,444],{"class":153,"line":154},[151,442,443],{"class":157},"test-service",[151,445,162],{"class":161},[151,447,448,450],{"class":153,"line":165},[151,449,255],{"class":157},[151,451,162],{"class":161},[151,453,454,457,459],{"class":153,"line":181},[151,455,456],{"class":157},"    SERVICE_NAME",[151,458,171],{"class":161},[151,460,461],{"class":174},"auth-service\n",[151,463,464,466,468],{"class":153,"line":192},[151,465,262],{"class":157},[151,467,171],{"class":161},[151,469,470],{"class":174},"staging\n",[151,472,473,475],{"class":153,"line":199},[151,474,275],{"class":157},[151,476,162],{"class":161},[151,478,479,481],{"class":153,"line":207},[151,480,282],{"class":161},[151,482,483],{"class":174},"run-tests-for $SERVICE_NAME in $ENVIRONMENT\n",[16,485,486],{},[46,487,488],{},"Mit Inputs:",[142,490,492],{"className":144,"code":491,"language":146,"meta":147,"style":147},"spec:\n  inputs:\n    environment:\n      type: string\n    service_name:\n      type: string\n\ntest-$[[ inputs.service_name ]]-$[[ inputs.environment ]]:\n  script:\n    - run-tests-for $[[ inputs.service_name ]] in $[[ inputs.environment ]]\n",[61,493,494,501,508,515,525,532,540,544,551,558],{"__ignoreMap":147},[151,495,496,499],{"class":153,"line":154},[151,497,498],{"class":157},"spec",[151,500,162],{"class":161},[151,502,503,506],{"class":153,"line":165},[151,504,505],{"class":157},"  inputs",[151,507,162],{"class":161},[151,509,510,513],{"class":153,"line":181},[151,511,512],{"class":157},"    environment",[151,514,162],{"class":161},[151,516,517,520,522],{"class":153,"line":192},[151,518,519],{"class":157},"      type",[151,521,171],{"class":161},[151,523,524],{"class":174},"string\n",[151,526,527,530],{"class":153,"line":199},[151,528,529],{"class":157},"    service_name",[151,531,162],{"class":161},[151,533,534,536,538],{"class":153,"line":207},[151,535,519],{"class":157},[151,537,171],{"class":161},[151,539,524],{"class":174},[151,541,542],{"class":153,"line":221},[151,543,196],{"emptyLinePlaceholder":195},[151,545,546,549],{"class":153,"line":305},[151,547,548],{"class":157},"test-$[[ inputs.service_name ]]-$[[ inputs.environment ]]",[151,550,162],{"class":161},[151,552,554,556],{"class":153,"line":553},9,[151,555,275],{"class":157},[151,557,162],{"class":161},[151,559,561,563],{"class":153,"line":560},10,[151,562,282],{"class":161},[151,564,565],{"class":174},"run-tests-for $[[ inputs.service_name ]] in $[[ inputs.environment ]]\n",[16,567,568,569,572,573,576,577,580],{},"Wird dies mehrfach mit unterschiedlichen Inputs eingebunden, entstehen Jobs wie ",[61,570,571],{},"test-auth-service-staging",", ",[61,574,575],{},"test-payment-service-production"," und ",[61,578,579],{},"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.",[16,582,583],{},"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.",[142,585,587],{"className":144,"code":586,"language":146,"meta":147,"style":147},"spec:\n  inputs:\n    environment:\n      type: string\n    database_url:\n      type: string\n    action:\n      type: string\n---\n$[[ inputs.action ]]-$[[ inputs.environment ]]:\n  script:\n    - echo \"Running $[[ inputs.action ]] in $[[ inputs.environment ]] environment\"\n    - echo \"Database URL is $[[ inputs.database_url ]]\"\n    - run-$[[ inputs.action ]] --env=$[[ inputs.environment ]] --db=$[[ inputs.database_url ]]\n",[61,588,589,595,601,607,615,622,630,637,645,651,658,665,673,681],{"__ignoreMap":147},[151,590,591,593],{"class":153,"line":154},[151,592,498],{"class":157},[151,594,162],{"class":161},[151,596,597,599],{"class":153,"line":165},[151,598,505],{"class":157},[151,600,162],{"class":161},[151,602,603,605],{"class":153,"line":181},[151,604,512],{"class":157},[151,606,162],{"class":161},[151,608,609,611,613],{"class":153,"line":192},[151,610,519],{"class":157},[151,612,171],{"class":161},[151,614,524],{"class":174},[151,616,617,620],{"class":153,"line":199},[151,618,619],{"class":157},"    database_url",[151,621,162],{"class":161},[151,623,624,626,628],{"class":153,"line":207},[151,625,519],{"class":157},[151,627,171],{"class":161},[151,629,524],{"class":174},[151,631,632,635],{"class":153,"line":221},[151,633,634],{"class":157},"    action",[151,636,162],{"class":161},[151,638,639,641,643],{"class":153,"line":305},[151,640,519],{"class":157},[151,642,171],{"class":161},[151,644,524],{"class":174},[151,646,647],{"class":153,"line":553},[151,648,650],{"class":649},"s7eDp","---\n",[151,652,653,656],{"class":153,"line":560},[151,654,655],{"class":157},"$[[ inputs.action ]]-$[[ inputs.environment ]]",[151,657,162],{"class":161},[151,659,661,663],{"class":153,"line":660},11,[151,662,275],{"class":157},[151,664,162],{"class":161},[151,666,668,670],{"class":153,"line":667},12,[151,669,282],{"class":161},[151,671,672],{"class":174},"echo \"Running $[[ inputs.action ]] in $[[ inputs.environment ]] environment\"\n",[151,674,676,678],{"class":153,"line":675},13,[151,677,282],{"class":161},[151,679,680],{"class":174},"echo \"Database URL is $[[ inputs.database_url ]]\"\n",[151,682,684,686],{"class":153,"line":683},14,[151,685,282],{"class":161},[151,687,688],{"class":174},"run-$[[ inputs.action ]] --env=$[[ inputs.environment ]] --db=$[[ inputs.database_url ]]\n",[16,690,691,692,694],{},"In der Haupt-Datei ",[61,693,139],{}," lässt sich das Template zweimal (oder öfter) mit unterschiedlichen Werten einbinden, ohne Namenskollisionen:",[142,696,698],{"className":144,"code":697,"language":146,"meta":147,"style":147},"include:\n  - local: 'templates/environment-template.yml'\n    inputs:\n      environment: test\n      database_url: test-db.example.com\n      action: tests\n  - local: 'templates/environment-template.yml'\n    inputs:\n      environment: production\n      database_url: prod-db.example.com\n      action: deploy\n",[61,699,700,706,717,724,734,744,754,764,770,779,787],{"__ignoreMap":147},[151,701,702,704],{"class":153,"line":154},[151,703,202],{"class":157},[151,705,162],{"class":161},[151,707,708,710,712,714],{"class":153,"line":165},[151,709,210],{"class":161},[151,711,213],{"class":157},[151,713,171],{"class":161},[151,715,716],{"class":174},"'templates/environment-template.yml'\n",[151,718,719,722],{"class":153,"line":181},[151,720,721],{"class":157},"    inputs",[151,723,162],{"class":161},[151,725,726,729,731],{"class":153,"line":192},[151,727,728],{"class":157},"      environment",[151,730,171],{"class":161},[151,732,733],{"class":174},"test\n",[151,735,736,739,741],{"class":153,"line":199},[151,737,738],{"class":157},"      database_url",[151,740,171],{"class":161},[151,742,743],{"class":174},"test-db.example.com\n",[151,745,746,749,751],{"class":153,"line":207},[151,747,748],{"class":157},"      action",[151,750,171],{"class":161},[151,752,753],{"class":174},"tests\n",[151,755,756,758,760,762],{"class":153,"line":221},[151,757,210],{"class":161},[151,759,213],{"class":157},[151,761,171],{"class":161},[151,763,716],{"class":174},[151,765,766,768],{"class":153,"line":305},[151,767,721],{"class":157},[151,769,162],{"class":161},[151,771,772,774,776],{"class":153,"line":553},[151,773,728],{"class":157},[151,775,171],{"class":161},[151,777,778],{"class":174},"production\n",[151,780,781,783,785],{"class":153,"line":560},[151,782,738],{"class":157},[151,784,171],{"class":161},[151,786,189],{"class":174},[151,788,789,791,793],{"class":153,"line":660},[151,790,748],{"class":157},[151,792,171],{"class":161},[151,794,795],{"class":174},"deploy\n",[16,797,798],{},"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.",[107,800,802],{"id":801},"validierung-und-typsicherheit","Validierung und Typsicherheit",[16,804,805],{},"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.",[16,807,808],{},"Der Nutzen der Typvalidierung zeigt sich an einem Beispiel.",[16,810,811],{},[46,812,813],{},"Ohne Typvalidierung (Variablen):",[142,815,817],{"className":144,"code":816,"language":146,"meta":147,"style":147},"variables:\n  ENABLE_TESTS: \"true\"  # Always a string\n  MAX_RETRIES: \"3\"      # Always a string\n\ndeploy_job:\n  script:\n    - if [ \"$ENABLE_TESTS\" = true ]; then  # This fails!\n        echo \"Running tests\"\n      fi\n    - retry_count=$((MAX_RETRIES + 1))      # String concatenation: \"31\"\n",[61,818,819,825,838,851,855,862,868,878,883,888],{"__ignoreMap":147},[151,820,821,823],{"class":153,"line":154},[151,822,158],{"class":157},[151,824,162],{"class":161},[151,826,827,830,832,835],{"class":153,"line":165},[151,828,829],{"class":157},"  ENABLE_TESTS",[151,831,171],{"class":161},[151,833,834],{"class":174},"\"true\"",[151,836,837],{"class":177},"  # Always a string\n",[151,839,840,843,845,848],{"class":153,"line":181},[151,841,842],{"class":157},"  MAX_RETRIES",[151,844,171],{"class":161},[151,846,847],{"class":174},"\"3\"",[151,849,850],{"class":177},"      # Always a string\n",[151,852,853],{"class":153,"line":192},[151,854,196],{"emptyLinePlaceholder":195},[151,856,857,860],{"class":153,"line":199},[151,858,859],{"class":157},"deploy_job",[151,861,162],{"class":161},[151,863,864,866],{"class":153,"line":207},[151,865,275],{"class":157},[151,867,162],{"class":161},[151,869,870,872,875],{"class":153,"line":221},[151,871,282],{"class":161},[151,873,874],{"class":174},"if [ \"$ENABLE_TESTS\" = true ]; then",[151,876,877],{"class":177},"  # This fails!\n",[151,879,880],{"class":153,"line":305},[151,881,882],{"class":174},"        echo \"Running tests\"\n",[151,884,885],{"class":153,"line":553},[151,886,887],{"class":174},"      fi\n",[151,889,890,892,895],{"class":153,"line":560},[151,891,282],{"class":161},[151,893,894],{"class":174},"retry_count=$((MAX_RETRIES + 1))",[151,896,897],{"class":177},"      # String concatenation: \"31\"\n",[16,899,900,901,903,904,907],{},"Das Problem: Die Boolean-Prüfung schlägt fehl, weil die Zeichenkette ",[61,902,834],{}," nicht gleich dem Boolean ",[61,905,906],{},"true"," ist.",[16,909,910],{},[46,911,912],{},"Mit Typvalidierung (Inputs):",[142,914,916],{"className":144,"code":915,"language":146,"meta":147,"style":147},"spec:\n  inputs:\n    enable_tests:\n      type: boolean\n      default: true\n    max_retries:\n      type: number\n      default: 3\n\ndeploy_job:\n  script:\n    - if [ \"$[[ inputs.enable_tests ]]\" = true ]; then  # Works correctly\n        echo \"Running tests\"\n      fi\n    - retry_count=$(($[[ inputs.max_retries ]] + 1))    # Math works: 4\n",[61,917,918,924,930,937,946,957,964,973,982,986,992,998,1008,1012,1016],{"__ignoreMap":147},[151,919,920,922],{"class":153,"line":154},[151,921,498],{"class":157},[151,923,162],{"class":161},[151,925,926,928],{"class":153,"line":165},[151,927,505],{"class":157},[151,929,162],{"class":161},[151,931,932,935],{"class":153,"line":181},[151,933,934],{"class":157},"    enable_tests",[151,936,162],{"class":161},[151,938,939,941,943],{"class":153,"line":192},[151,940,519],{"class":157},[151,942,171],{"class":161},[151,944,945],{"class":174},"boolean\n",[151,947,948,951,953],{"class":153,"line":199},[151,949,950],{"class":157},"      default",[151,952,171],{"class":161},[151,954,956],{"class":955},"sYu0t","true\n",[151,958,959,962],{"class":153,"line":207},[151,960,961],{"class":157},"    max_retries",[151,963,162],{"class":161},[151,965,966,968,970],{"class":153,"line":221},[151,967,519],{"class":157},[151,969,171],{"class":161},[151,971,972],{"class":174},"number\n",[151,974,975,977,979],{"class":153,"line":305},[151,976,950],{"class":157},[151,978,171],{"class":161},[151,980,981],{"class":955},"3\n",[151,983,984],{"class":153,"line":553},[151,985,196],{"emptyLinePlaceholder":195},[151,987,988,990],{"class":153,"line":560},[151,989,859],{"class":157},[151,991,162],{"class":161},[151,993,994,996],{"class":153,"line":660},[151,995,275],{"class":157},[151,997,162],{"class":161},[151,999,1000,1002,1005],{"class":153,"line":667},[151,1001,282],{"class":161},[151,1003,1004],{"class":174},"if [ \"$[[ inputs.enable_tests ]]\" = true ]; then",[151,1006,1007],{"class":177},"  # Works correctly\n",[151,1009,1010],{"class":153,"line":675},[151,1011,882],{"class":174},[151,1013,1014],{"class":153,"line":683},[151,1015,887],{"class":174},[151,1017,1019,1021,1024],{"class":153,"line":1018},15,[151,1020,282],{"class":161},[151,1022,1023],{"class":174},"retry_count=$(($[[ inputs.max_retries ]] + 1))",[151,1025,1026],{"class":177},"    # Math works: 4\n",[16,1028,1029,1030,1033,1034,1036],{},"Der praktische Unterschied: Wird eine Pipeline mit ",[61,1031,1032],{},"ENABLE_TESTS = yes"," statt ",[61,1035,906],{}," 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.",[107,1038,1040],{"id":1039},"sicherheit-und-zugriffskontrolle","Sicherheit und Zugriffskontrolle",[16,1042,1043],{},"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.",[107,1045,1047],{"id":1046},"geltungsbereich-und-lebenszyklus","Geltungsbereich und Lebenszyklus",[16,1049,1050,1051,1054,1055,1057],{},"Werden Variablen über das Schlüsselwort ",[61,1052,1053],{},"variables:"," auf oberster Ebene der ",[61,1056,139],{}," 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.",[16,1059,1060],{},"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.",[26,1062,1064],{"id":1063},"variablen-und-inputs-zusammen-nutzen","Variablen und Inputs zusammen nutzen",[16,1066,1067],{},"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.",[16,1069,1070],{},"Ein praxisnahes Beispiel dazu.",[16,1072,1073],{},[46,1074,1075,1076,1078],{},"Variablenexpansion in ",[61,1077,418],{},"-Bedingungen",[16,1080,1081,1082,1085],{},"Eine häufige Hürde entsteht, wenn Variablen, die weitere Variablenreferenzen enthalten, in ",[61,1083,1084],{},"rules:if","-Bedingungen verwendet werden. GitLab expandiert Variablen bei der Regelauswertung nur eine Ebene tief, was zu unerwartetem Verhalten führen kann:",[142,1087,1089],{"className":144,"code":1088,"language":146,"meta":147,"style":147},"# This doesn't work as expected\nvariables:\n  TARGET_ENV:\n    value: \"${CI_COMMIT_REF_SLUG}\"\n\ndeploy-job:\n  rules:\n    - if: '$TARGET_ENV == \"production\"'  # Compares \"${CI_COMMIT_REF_SLUG}\" != \"production\"\n      variables:\n        DEPLOY_MODE: \"blue-green\"\n",[61,1090,1091,1096,1102,1109,1119,1123,1130,1137,1152,1159],{"__ignoreMap":147},[151,1092,1093],{"class":153,"line":154},[151,1094,1095],{"class":177},"# This doesn't work as expected\n",[151,1097,1098,1100],{"class":153,"line":165},[151,1099,158],{"class":157},[151,1101,162],{"class":161},[151,1103,1104,1107],{"class":153,"line":181},[151,1105,1106],{"class":157},"  TARGET_ENV",[151,1108,162],{"class":161},[151,1110,1111,1114,1116],{"class":153,"line":192},[151,1112,1113],{"class":157},"    value",[151,1115,171],{"class":161},[151,1117,1118],{"class":174},"\"${CI_COMMIT_REF_SLUG}\"\n",[151,1120,1121],{"class":153,"line":199},[151,1122,196],{"emptyLinePlaceholder":195},[151,1124,1125,1128],{"class":153,"line":207},[151,1126,1127],{"class":157},"deploy-job",[151,1129,162],{"class":161},[151,1131,1132,1135],{"class":153,"line":221},[151,1133,1134],{"class":157},"  rules",[151,1136,162],{"class":161},[151,1138,1139,1141,1144,1146,1149],{"class":153,"line":305},[151,1140,282],{"class":161},[151,1142,1143],{"class":157},"if",[151,1145,171],{"class":161},[151,1147,1148],{"class":174},"'$TARGET_ENV == \"production\"'",[151,1150,1151],{"class":177},"  # Compares \"${CI_COMMIT_REF_SLUG}\" != \"production\"\n",[151,1153,1154,1157],{"class":153,"line":553},[151,1155,1156],{"class":157},"      variables",[151,1158,162],{"class":161},[151,1160,1161,1164,1166],{"class":153,"line":560},[151,1162,1163],{"class":157},"        DEPLOY_MODE",[151,1165,171],{"class":161},[151,1167,1168],{"class":174},"\"blue-green\"\n",[16,1170,1171,1172,1175],{},"Die Funktion ",[61,1173,1174],{},"expand_vars"," löst dies, indem sie in Inputs eine vollständige Variablenexpansion erzwingt:",[142,1177,1179],{"className":144,"code":1178,"language":146,"meta":147,"style":147},"spec:\n  inputs:\n    target_environment:\n      description: \"Target deployment environment\"\n      default: \"${CI_COMMIT_REF_SLUG}\"\n---\ndeploy-job:\n  rules:\n    - if: '\"$[[ inputs.target_environment | expand_vars ]]\" == \"production\"'\n      variables:\n        DEPLOY_MODE: \"blue-green\"\n        APPROVAL_REQUIRED: \"true\"\n    - when: always\n      variables:\n        DEPLOY_MODE: \"rolling\"\n        APPROVAL_REQUIRED: \"false\"\n  script:\n    - echo \"Target: $[[ inputs.target_environment | expand_vars ]]\"\n    - echo \"Deploy mode: ${DEPLOY_MODE}\"\n",[61,1180,1181,1187,1193,1200,1210,1218,1222,1228,1234,1245,1251,1259,1269,1281,1287,1296,1306,1313,1326],{"__ignoreMap":147},[151,1182,1183,1185],{"class":153,"line":154},[151,1184,498],{"class":157},[151,1186,162],{"class":161},[151,1188,1189,1191],{"class":153,"line":165},[151,1190,505],{"class":157},[151,1192,162],{"class":161},[151,1194,1195,1198],{"class":153,"line":181},[151,1196,1197],{"class":157},"    target_environment",[151,1199,162],{"class":161},[151,1201,1202,1205,1207],{"class":153,"line":192},[151,1203,1204],{"class":157},"      description",[151,1206,171],{"class":161},[151,1208,1209],{"class":174},"\"Target deployment environment\"\n",[151,1211,1212,1214,1216],{"class":153,"line":199},[151,1213,950],{"class":157},[151,1215,171],{"class":161},[151,1217,1118],{"class":174},[151,1219,1220],{"class":153,"line":207},[151,1221,650],{"class":649},[151,1223,1224,1226],{"class":153,"line":221},[151,1225,1127],{"class":157},[151,1227,162],{"class":161},[151,1229,1230,1232],{"class":153,"line":305},[151,1231,1134],{"class":157},[151,1233,162],{"class":161},[151,1235,1236,1238,1240,1242],{"class":153,"line":553},[151,1237,282],{"class":161},[151,1239,1143],{"class":157},[151,1241,171],{"class":161},[151,1243,1244],{"class":174},"'\"$[[ inputs.target_environment | expand_vars ]]\" == \"production\"'\n",[151,1246,1247,1249],{"class":153,"line":560},[151,1248,1156],{"class":157},[151,1250,162],{"class":161},[151,1252,1253,1255,1257],{"class":153,"line":660},[151,1254,1163],{"class":157},[151,1256,171],{"class":161},[151,1258,1168],{"class":174},[151,1260,1261,1264,1266],{"class":153,"line":667},[151,1262,1263],{"class":157},"        APPROVAL_REQUIRED",[151,1265,171],{"class":161},[151,1267,1268],{"class":174},"\"true\"\n",[151,1270,1271,1273,1276,1278],{"class":153,"line":675},[151,1272,282],{"class":161},[151,1274,1275],{"class":157},"when",[151,1277,171],{"class":161},[151,1279,1280],{"class":174},"always\n",[151,1282,1283,1285],{"class":153,"line":683},[151,1284,1156],{"class":157},[151,1286,162],{"class":161},[151,1288,1289,1291,1293],{"class":153,"line":1018},[151,1290,1163],{"class":157},[151,1292,171],{"class":161},[151,1294,1295],{"class":174},"\"rolling\"\n",[151,1297,1299,1301,1303],{"class":153,"line":1298},16,[151,1300,1263],{"class":157},[151,1302,171],{"class":161},[151,1304,1305],{"class":174},"\"false\"\n",[151,1307,1309,1311],{"class":153,"line":1308},17,[151,1310,275],{"class":157},[151,1312,162],{"class":161},[151,1314,1316,1318,1321,1323],{"class":153,"line":1315},18,[151,1317,282],{"class":161},[151,1319,1320],{"class":157},"echo \"Target",[151,1322,171],{"class":161},[151,1324,1325],{"class":174},"$[[ inputs.target_environment | expand_vars ]]\"\n",[151,1327,1329,1331,1334,1336],{"class":153,"line":1328},19,[151,1330,282],{"class":161},[151,1332,1333],{"class":157},"echo \"Deploy mode",[151,1335,171],{"class":161},[151,1337,1338],{"class":174},"${DEPLOY_MODE}\"\n",[107,1340,1342],{"id":1341},"warum-das-zählt","Warum das zählt",[16,1344,1345,1346,1348,1349,1352,1353,1356],{},"Ohne ",[61,1347,1174],{}," werten Regelbedingungen die wörtliche Variablenreferenz aus (etwa ",[61,1350,1351],{},"\"${CI_COMMIT_REF_SLUG}\"",") statt des expandierten Werts (etwa ",[61,1354,1355],{},"\"production\"","). Das führt zu Regeln, die entgegen der Erwartung nie zutreffen, und bricht die bedingte Pipeline-Logik.",[16,1358,1359],{},[46,1360,1361,1362,1364],{},"Wichtige Hinweise zu ",[61,1363,1174],{},":",[1366,1367,1368,1374,1377,1380],"ul",{},[373,1369,1370,1371,1373],{},"Unterstützt werden nur Variablen, die sich mit dem Schlüsselwort ",[61,1372,202],{}," verwenden lassen.",[373,1375,1376],{},"Die Variablen dürfen nicht maskiert (nicht als protected/masked markiert) sein.",[373,1378,1379],{},"Verschachtelte Variablenexpansion wird nicht unterstützt.",[373,1381,1382,1383,1385,1386,80],{},"Regelbedingungen mit ",[61,1384,1174],{}," müssen korrekt in Anführungszeichen gesetzt werden: ",[61,1387,1388],{},"'\"$[[ inputs.name | expand_vars ]]\" == \"value\"'",[16,1390,1391],{},"Dieses Muster löst die Beschränkung auf einstufige Variablenexpansion und funktioniert für jede bedingte Logik, die vollständig aufgelöste Variablenwerte vergleicht.",[107,1393,1395],{"id":1394},"funktionsverkettung-für-fortgeschrittene-verarbeitung","Funktionsverkettung für fortgeschrittene Verarbeitung",[16,1397,1398,1399,1401,1402,1405],{},"Neben ",[61,1400,1174],{}," lassen sich Funktionen wie ",[61,1403,1404],{},"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.",[142,1407,1409],{"className":144,"code":1408,"language":146,"meta":147,"style":147},"spec:\n  inputs:\n    service_identifier:\n      default: 'service-$CI_PROJECT_NAME-$CI_COMMIT_REF_SLUG'\n---\ncreate-resource:\n  script:\n    - resource_name=$[[ inputs.service_identifier | expand_vars | truncate(0,50) ]]\n",[61,1410,1411,1417,1423,1430,1439,1443,1450,1456],{"__ignoreMap":147},[151,1412,1413,1415],{"class":153,"line":154},[151,1414,498],{"class":157},[151,1416,162],{"class":161},[151,1418,1419,1421],{"class":153,"line":165},[151,1420,505],{"class":157},[151,1422,162],{"class":161},[151,1424,1425,1428],{"class":153,"line":181},[151,1426,1427],{"class":157},"    service_identifier",[151,1429,162],{"class":161},[151,1431,1432,1434,1436],{"class":153,"line":192},[151,1433,950],{"class":157},[151,1435,171],{"class":161},[151,1437,1438],{"class":174},"'service-$CI_PROJECT_NAME-$CI_COMMIT_REF_SLUG'\n",[151,1440,1441],{"class":153,"line":199},[151,1442,650],{"class":649},[151,1444,1445,1448],{"class":153,"line":207},[151,1446,1447],{"class":157},"create-resource",[151,1449,162],{"class":161},[151,1451,1452,1454],{"class":153,"line":221},[151,1453,275],{"class":157},[151,1455,162],{"class":161},[151,1457,1458,1460],{"class":153,"line":305},[151,1459,282],{"class":161},[151,1461,1462],{"class":174},"resource_name=$[[ inputs.service_identifier | expand_vars | truncate(0,50) ]]\n",[16,1464,1465],{},"Diese Integrationsmöglichkeit erlaubt es, Inputs schrittweise einzuführen und dabei die bestehende Variableninfrastruktur weiter zu nutzen – der Migrationsweg wird dadurch deutlich sanfter.",[107,1467,1469],{"id":1468},"von-reinen-komponenten-zu-vollständigen-pipelines","Von reinen Komponenten zu vollständigen Pipelines",[16,1471,1472,1473,1476],{},"Bis GitLab 17.11 ließen sich Inputs nur in Komponenten und Templates über die ",[61,1474,1475],{},"include:","-Syntax verwenden. Das beschränkte ihren Einsatz auf wiederverwendbare CI/CD-Konfigurationen und deckte den umfassenderen Bedarf an dynamischer Pipeline-Anpassung nicht ab.",[107,1478,1480],{"id":1479},"pipeline-weite-unterstützung-für-inputs","Pipeline-weite Unterstützung für Inputs",[16,1482,1483],{},"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:",[1366,1485,1486,1492,1498],{},[373,1487,1488,1491],{},[46,1489,1490],{},"Geplante Pipelines:"," Inputs mit Standardwerten für automatisierte Läufe definieren und bei Bedarf manuell überschreiben.",[373,1493,1494,1497],{},[46,1495,1496],{},"Nachgelagerte Pipelines:"," Strukturierte Inputs mit Validierung und Typsicherheit an Child- und Multi-Projekt-Pipelines übergeben.",[373,1499,1500,1503],{},[46,1501,1502],{},"Manuelle Pipelines:"," Nutzenden ein sauberes, validiertes Formular bereitstellen.",[16,1505,1506],{},"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.",[26,1508,1510],{"id":1509},"zusammenfassung","Zusammenfassung",[16,1512,1513],{},"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.",[16,1515,1516,1517,1519],{},"Da Variablen tief in bestehenden Abläufen verankert sind, gibt es Brücken zwischen beiden Systemen. Die Funktion ",[61,1518,1174],{}," und weitere Input-Fähigkeiten erlauben eine schrittweise Einführung, ohne die bestehende Variableninfrastruktur aufzugeben.",[16,1521,1522,1523,1528],{},"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 ",[115,1524,1527],{"href":1525,"rel":1526},"https://gitlab.com/explore/catalog",[],"CI/CD-Katalog von GitLab",", in dem wiederverwendbare Komponenten mit typisierten Schnittstellen zu wirkungsvollen Bausteinen für DevOps-Abläufe werden.",[26,1530,1532],{"id":1531},"weiterführend","Weiterführend",[1366,1534,1535,1542,1549,1556],{},[373,1536,1537],{},[115,1538,1541],{"href":1539,"rel":1540},"https://about.gitlab.com/blog/how-to-include-file-references-in-your-ci-cd-components/",[],"Dateireferenzen in CI/CD-Komponenten einbinden",[373,1543,1544],{},[115,1545,1548],{"href":1546,"rel":1547},"https://docs.gitlab.com/ci/inputs/",[],"Dokumentation zu CI/CD Inputs",[373,1550,1551],{},[115,1552,1555],{"href":1553,"rel":1554},"https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/",[],"CI/CD-Katalog wird allgemein verfügbar",[373,1557,1558],{},[115,1559,1562],{"href":1560,"rel":1561},"https://about.gitlab.com/de-de/blog/demystifying-ci-cd-variables/",[],"GitLab-Umgebungsvariablen erklärt",[1564,1565,1566],"style",{},"html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}",{"title":147,"searchDepth":165,"depth":165,"links":1568},[1569,1570,1571,1578,1584,1585],{"id":28,"depth":165,"text":29},{"id":35,"depth":165,"text":36},{"id":101,"depth":165,"text":102,"children":1572},[1573,1574,1575,1576,1577],{"id":109,"depth":181,"text":110},{"id":407,"depth":181,"text":408},{"id":801,"depth":181,"text":802},{"id":1039,"depth":181,"text":1040},{"id":1046,"depth":181,"text":1047},{"id":1063,"depth":165,"text":1064,"children":1579},[1580,1581,1582,1583],{"id":1341,"depth":181,"text":1342},{"id":1394,"depth":181,"text":1395},{"id":1468,"depth":181,"text":1469},{"id":1479,"depth":181,"text":1480},{"id":1509,"depth":165,"text":1510},{"id":1531,"depth":165,"text":1532},"product","2026-07-06","Wie CI/CD Inputs Parameter typsicher und validiert übergeben und fehleranfällige Variablen ersetzen – für verlässlichere, wartbarere Pipelines.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749658912/Blog/Hero%20Images/blog-image-template-1800x945__20_.png",{},"/de-de/blog/ci-cd-inputs-secure-and-preferred-method-to-pass-parameters-to-a-pipeline",{"noIndex":1591,"title":1596,"description":1597},"CI/CD Inputs: sichere Parameterübergabe an Pipelines","CI/CD Inputs übergeben Parameter typsicher und validiert an Pipelines – mit klaren Verträgen statt fehleranfälliger Variablen. Grundlagen und Praxisbeispiele.","ci-cd-inputs-secure-and-preferred-method-to-pass-parameters-to-a-pipeline","de-de/blog/ci-cd-inputs-secure-and-preferred-method-to-pass-parameters-to-a-pipeline",[1601,1586,1602],"CI/CD","security","BlogPost","vuO_HkloWOo27br2maZ37NwgThRgS1tGtHFK2xST9M8",{"logo":1606,"freeTrial":1611,"sales":1616,"login":1621,"items":1626,"search":1954,"minimal":1988,"duo":2006,"switchNav":2015,"pricingDeployment":2026},{"config":1607},{"href":1608,"dataGaName":1609,"dataGaLocation":1610},"/de-de/","gitlab logo","header",{"text":1612,"config":1613},"Kostenlose Testversion anfordern",{"href":1614,"dataGaName":1615,"dataGaLocation":1610},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/de-de&glm_content=default-saas-trial/","free trial",{"text":1617,"config":1618},"Demo anfordern",{"href":1619,"dataGaName":1620,"dataGaLocation":1610},"/de-de/sales/?contact-topic=request-demo","sales",{"text":1622,"config":1623},"Anmelden",{"href":1624,"dataGaName":1625,"dataGaLocation":1610},"https://gitlab.com/users/sign_in/","sign in",[1627,1656,1757,1762,1876,1932],{"text":1628,"config":1629,"menu":1631},"Plattform",{"dataNavLevelOne":1630},"platform",{"type":1632,"columns":1633},"cards",[1634,1640,1648],{"title":1628,"description":1635,"link":1636},"Die intelligente Orchestrierungsplattform für DevSecOps",{"text":1637,"config":1638},"Die Plattform erkunden",{"href":1639,"dataGaName":1630,"dataGaLocation":1610},"/de-de/platform/",{"title":1641,"description":1642,"link":1643},"GitLab Duo Agent Platform","Agentische KI für den gesamten Software-Lebenszyklus",{"text":1644,"config":1645},"Lerne GitLab Duo kennen",{"href":1646,"dataGaName":1647,"dataGaLocation":1610},"/de-de/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":1649,"description":1650,"link":1651},"Warum GitLab?","Erfahre, warum sich Unternehmen für GitLab entscheiden",{"text":1652,"config":1653},"Mehr erfahren",{"href":1654,"dataGaName":1655,"dataGaLocation":1610},"/de-de/why-gitlab/","why gitlab",{"text":1657,"left":195,"config":1658,"menu":1660},"Produkt",{"dataNavLevelOne":1659},"solutions",{"type":1661,"link":1662,"columns":1666,"feature":1736},"lists",{"text":1663,"config":1664},"Alle Lösungen anzeigen",{"href":1665,"dataGaName":1659,"dataGaLocation":1610},"/de-de/solutions/",[1667,1691,1714],{"title":1668,"description":1669,"link":1670,"items":1675},"Automatisierung","CI/CD und Automatisierung zur Beschleunigung der Bereitstellung",{"config":1671},{"icon":1672,"href":1673,"dataGaName":1674,"dataGaLocation":1610},"AutomatedCodeAlt","/de-de/solutions/delivery-automation/","automated software delivery",[1676,1679,1682,1687],{"text":1601,"config":1677},{"href":1678,"dataGaLocation":1610,"dataGaName":1601},"/de-de/solutions/continuous-integration/",{"text":1641,"config":1680},{"href":1646,"dataGaLocation":1610,"dataGaName":1681},"gitlab duo agent platform - product menu",{"text":1683,"config":1684},"Quellcodeverwaltung",{"href":1685,"dataGaLocation":1610,"dataGaName":1686},"/de-de/solutions/source-code-management/","Source Code Management",{"text":1688,"config":1689},"Automatische Softwarebereitstellung",{"href":1673,"dataGaLocation":1610,"dataGaName":1690},"Automated software delivery",{"title":1692,"description":1693,"link":1694,"items":1699},"Sicherheit","Entwickle Code schneller ohne Abstriche bei der Sicherheit",{"config":1695},{"href":1696,"dataGaName":1697,"dataGaLocation":1610,"icon":1698},"/de-de/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[1700,1704,1709],{"text":1701,"config":1702},"Anwendungssicherheitstests",{"href":1696,"dataGaName":1703,"dataGaLocation":1610},"Application security testing",{"text":1705,"config":1706},"Schutz der Software-Lieferkette",{"href":1707,"dataGaLocation":1610,"dataGaName":1708},"/de-de/solutions/supply-chain/","Software supply chain security",{"text":1710,"config":1711},"Software-Compliance",{"href":1712,"dataGaName":1713,"dataGaLocation":1610},"/de-de/solutions/software-compliance/","software compliance",{"title":1715,"link":1716,"items":1721},"Messung",{"config":1717},{"icon":1718,"href":1719,"dataGaName":1720,"dataGaLocation":1610},"DigitalTransformation","/de-de/solutions/visibility-measurement/","visibility and measurement",[1722,1726,1731],{"text":1723,"config":1724},"Sichtbarkeit und Messung",{"href":1719,"dataGaLocation":1610,"dataGaName":1725},"Visibility and Measurement",{"text":1727,"config":1728},"Wertstrommanagement",{"href":1729,"dataGaLocation":1610,"dataGaName":1730},"/de-de/solutions/value-stream-management/","Value Stream Management",{"text":1732,"config":1733},"Analysen und Einblicke",{"href":1734,"dataGaLocation":1610,"dataGaName":1735},"/de-de/solutions/analytics-and-insights/","Analytics and insights",{"title":1737,"type":1661,"items":1738},"GitLab für",[1739,1745,1751],{"text":1740,"config":1741},"Enterprise",{"icon":1742,"href":1743,"dataGaLocation":1610,"dataGaName":1744},"Building","/de-de/enterprise/","enterprise",{"text":1746,"config":1747},"Kleinunternehmen",{"icon":1748,"href":1749,"dataGaLocation":1610,"dataGaName":1750},"Work","/de-de/small-business/","small business",{"text":1752,"config":1753},"Öffentlicher Sektor",{"icon":1754,"href":1755,"dataGaLocation":1610,"dataGaName":1756},"Organization","/de-de/solutions/public-sector/","public sector",{"text":1758,"config":1759},"Preise",{"href":1760,"dataGaName":1761,"dataGaLocation":1610,"dataNavLevelOne":1761},"/de-de/pricing/","pricing",{"text":1763,"config":1764,"menu":1766},"Ressourcen",{"dataNavLevelOne":1765},"resources",{"type":1661,"link":1767,"columns":1771,"feature":1865},{"text":1768,"config":1769},"Alle Ressourcen anzeigen",{"href":1770,"dataGaName":1765,"dataGaLocation":1610},"/de-de/resources/",[1772,1805,1832],{"title":1773,"items":1774},"Erste Schritte",[1775,1780,1785,1790,1795,1800],{"text":1776,"config":1777},"Installieren",{"href":1778,"dataGaName":1779,"dataGaLocation":1610},"/de-de/install/","install",{"text":1781,"config":1782},"Kurzanleitungen",{"href":1783,"dataGaName":1784,"dataGaLocation":1610},"/de-de/get-started/","quick setup checklists",{"text":1786,"config":1787},"Lernen",{"href":1788,"dataGaLocation":1610,"dataGaName":1789},"https://university.gitlab.com/","learn",{"text":1791,"config":1792},"Produktdokumentation",{"href":1793,"dataGaName":1794,"dataGaLocation":1610},"https://docs.gitlab.com/","product documentation",{"text":1796,"config":1797},"Best-Practice-Videos",{"href":1798,"dataGaName":1799,"dataGaLocation":1610},"/de-de/getting-started-videos/","best practice videos",{"text":1801,"config":1802},"Integrationen",{"href":1803,"dataGaName":1804,"dataGaLocation":1610},"/de-de/integrations/","integrations",{"title":1806,"items":1807},"Entdecken",[1808,1813,1818,1823,1827],{"text":1809,"config":1810},"Kundenerfolge",{"href":1811,"dataGaName":1812,"dataGaLocation":1610},"/de-de/customers/","customer success stories",{"text":1814,"config":1815},"Blog",{"href":1816,"dataGaName":1817,"dataGaLocation":1610},"/de-de/blog/","blog",{"text":1819,"config":1820},"Demo-Hub",{"href":1821,"dataGaName":1822,"dataGaLocation":1610},"/de-de/demo-hub/","demo hub",{"text":1824,"config":1825},"The Source",{"href":1826,"dataGaName":1817,"dataGaLocation":1610},"/de-de/the-source/",{"text":1828,"config":1829},"Remote",{"href":1830,"dataGaName":1831,"dataGaLocation":1610},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1833,"items":1834},"Vernetzen",[1835,1840,1845,1850,1855,1860],{"text":1836,"config":1837},"GitLab-Services",{"href":1838,"dataGaName":1839,"dataGaLocation":1610},"/de-de/services/","services",{"text":1841,"config":1842},"Beitragen",{"href":1843,"dataGaName":1844,"dataGaLocation":1610},"https://contributors.gitlab.com","contribute",{"text":1846,"config":1847},"Community",{"href":1848,"dataGaName":1849,"dataGaLocation":1610},"/community/","community",{"text":1851,"config":1852},"Forum",{"href":1853,"dataGaName":1854,"dataGaLocation":1610},"https://forum.gitlab.com/","forum",{"text":1856,"config":1857},"Veranstaltungen",{"href":1858,"dataGaName":1859,"dataGaLocation":1610},"/events/","events",{"text":1861,"config":1862},"Partner",{"href":1863,"dataGaName":1864,"dataGaLocation":1610},"/de-de/partners/","partners",{"config":1866,"title":1869,"text":1870,"link":1871},{"background":1867,"textColor":1868},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1777322348/qpq8yrgn8knii57omj0c.png')","#000","Neues bei GitLab","Über die neuesten Funktionen und Verbesserungen auf dem Laufenden bleiben.",{"text":1872,"config":1873},"Aktuelle Nachrichten",{"href":1874,"dataGaName":1875,"dataGaLocation":1610},"/de-de/whats-new/","whats new",{"text":1877,"config":1878,"menu":1880},"Unternehmen",{"dataNavLevelOne":1879},"company",{"type":1661,"columns":1881},[1882],{"items":1883},[1884,1889,1895,1897,1902,1907,1912,1917,1922,1927],{"text":1885,"config":1886},"Über",{"href":1887,"dataGaName":1888,"dataGaLocation":1610},"/de-de/company/","about",{"text":1890,"config":1891,"footerGa":1894},"Karriere",{"href":1892,"dataGaName":1893,"dataGaLocation":1610},"/jobs/","jobs",{"dataGaName":1893},{"text":1856,"config":1896},{"href":1858,"dataGaName":1859,"dataGaLocation":1610},{"text":1898,"config":1899},"Geschäftsführung",{"href":1900,"dataGaName":1901,"dataGaLocation":1610},"/company/team/e-group/","leadership",{"text":1903,"config":1904},"Handbuch",{"href":1905,"dataGaName":1906,"dataGaLocation":1610},"https://handbook.gitlab.com/","handbook",{"text":1908,"config":1909},"Investor Relations",{"href":1910,"dataGaName":1911,"dataGaLocation":1610},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1913,"config":1914},"Trust Center",{"href":1915,"dataGaName":1916,"dataGaLocation":1610},"/de-de/security/","trust center",{"text":1918,"config":1919},"AI Transparency Center",{"href":1920,"dataGaName":1921,"dataGaLocation":1610},"/de-de/ai-transparency-center/","ai transparency center",{"text":1923,"config":1924},"Newsletter",{"href":1925,"dataGaName":1926,"dataGaLocation":1610},"/company/contact/#contact-forms","newsletter",{"text":1928,"config":1929},"Presse",{"href":1930,"dataGaName":1931,"dataGaLocation":1610},"/press/","press",{"text":1933,"config":1934,"menu":1935},"Kontakt",{"dataNavLevelOne":1879},{"type":1661,"columns":1936},[1937],{"items":1938},[1939,1944,1949],{"text":1940,"config":1941},"Vertrieb kontaktieren",{"href":1942,"dataGaName":1943,"dataGaLocation":1610},"/de-de/sales/","talk to sales",{"text":1945,"config":1946},"Support-Portal",{"href":1947,"dataGaName":1948,"dataGaLocation":1610},"https://support.gitlab.com/hc/en-us","support portal",{"text":1950,"config":1951},"Kundenportal",{"href":1952,"dataGaName":1953,"dataGaLocation":1610},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1955,"login":1956,"suggestions":1963},"Schließen",{"text":1957,"link":1958},"Um Repositorys und Projekte zu durchsuchen, melde dich an bei",{"text":1959,"config":1960},"gitlab.com",{"href":1624,"dataGaName":1961,"dataGaLocation":1962},"search login","search",{"text":1964,"default":1965},"Vorschläge",[1966,1968,1973,1975,1980,1985],{"text":1641,"config":1967},{"href":1646,"dataGaName":1641,"dataGaLocation":1962},{"text":1969,"config":1970},"Codevorschläge (KI)",{"href":1971,"dataGaName":1972,"dataGaLocation":1962},"/de-de/solutions/code-suggestions/","Code Suggestions (AI)",{"text":1601,"config":1974},{"href":1678,"dataGaName":1601,"dataGaLocation":1962},{"text":1976,"config":1977},"GitLab auf AWS",{"href":1978,"dataGaName":1979,"dataGaLocation":1962},"/de-de/partners/technology-partners/aws/","GitLab on AWS",{"text":1981,"config":1982},"GitLab auf Google Cloud",{"href":1983,"dataGaName":1984,"dataGaLocation":1962},"/de-de/partners/technology-partners/google-cloud-platform/","GitLab on Google Cloud",{"text":1649,"config":1986},{"href":1654,"dataGaName":1987,"dataGaLocation":1962},"Why GitLab?",{"freeTrial":1989,"mobileIcon":1994,"desktopIcon":1999,"secondaryButton":2002},{"text":1990,"config":1991},"Kostenlos testen",{"href":1992,"dataGaName":1615,"dataGaLocation":1993},"https://gitlab.com/-/trials/new/","nav",{"altText":1995,"config":1996},"GitLab-Symbol",{"src":1997,"dataGaName":1998,"dataGaLocation":1993},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1995,"config":2000},{"src":2001,"dataGaName":1998,"dataGaLocation":1993},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1773,"config":2003},{"href":2004,"dataGaName":2005,"dataGaLocation":1993},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/de-de/get-started/","get started",{"freeTrial":2007,"mobileIcon":2011,"desktopIcon":2013},{"text":2008,"config":2009},"Mehr über GitLab Duo erfahren",{"href":1646,"dataGaName":2010,"dataGaLocation":1993},"gitlab duo",{"altText":1995,"config":2012},{"src":1997,"dataGaName":1998,"dataGaLocation":1993},{"altText":1995,"config":2014},{"src":2001,"dataGaName":1998,"dataGaLocation":1993},{"button":2016,"mobileIcon":2021,"desktopIcon":2023},{"text":2017,"config":2018},"/Option",{"href":2019,"dataGaName":2020,"dataGaLocation":1993},"#contact","switch",{"altText":1995,"config":2022},{"src":1997,"dataGaName":1998,"dataGaLocation":1993},{"altText":1995,"config":2024},{"src":2025,"dataGaName":1998,"dataGaLocation":1993},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":2027,"mobileIcon":2032,"desktopIcon":2034},{"text":2028,"config":2029},"Zurück zur Preisübersicht",{"href":1760,"dataGaName":2030,"dataGaLocation":1993,"icon":2031},"back to pricing","GoBack",{"altText":1995,"config":2033},{"src":1997,"dataGaName":1998,"dataGaLocation":1993},{"altText":1995,"config":2035},{"src":2001,"dataGaName":1998,"dataGaLocation":1993},{"title":2037,"button":2038,"config":2042},"GitLab Orbit ist da: die Kontextebene für KI-Agenten",{"text":1652,"config":2039},{"href":2040,"dataGaName":2041,"dataGaLocation":1610},"/de-de/gitlab-orbit/","orbit",{"layout":2043,"disabled":1591},"release",{"data":2045},{"text":2046,"source":2047,"edit":2053,"contribute":2058,"config":2063,"items":2068,"minimal":2274},"Git ist eine Marke von Software Freedom Conservancy und unsere Verwendung von „GitLab“ erfolgt unter Lizenz.",{"text":2048,"config":2049},"Quelltext der Seite anzeigen",{"href":2050,"dataGaName":2051,"dataGaLocation":2052},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":2054,"config":2055},"Diese Seite bearbeiten",{"href":2056,"dataGaName":2057,"dataGaLocation":2052},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":2059,"config":2060},"Beteilige dich",{"href":2061,"dataGaName":2062,"dataGaLocation":2052},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":2064,"facebook":2065,"youtube":2066,"linkedin":2067},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[2069,2114,2167,2209,2241],{"title":1758,"links":2070,"subMenu":2085},[2071,2075,2080],{"text":2072,"config":2073},"Tarife anzeigen",{"href":1760,"dataGaName":2074,"dataGaLocation":2052},"view plans",{"text":2076,"config":2077},"Vorteile von Premium",{"href":2078,"dataGaName":2079,"dataGaLocation":2052},"/de-de/pricing/premium/","why premium",{"text":2081,"config":2082},"Vorteile von Ultimate",{"href":2083,"dataGaName":2084,"dataGaLocation":2052},"/de-de/pricing/ultimate/","why ultimate",[2086],{"title":1933,"links":2087},[2088,2090,2092,2094,2099,2104,2109],{"text":1940,"config":2089},{"href":1942,"dataGaName":1620,"dataGaLocation":2052},{"text":1945,"config":2091},{"href":1947,"dataGaName":1948,"dataGaLocation":2052},{"text":1950,"config":2093},{"href":1952,"dataGaName":1953,"dataGaLocation":2052},{"text":2095,"config":2096},"Status",{"href":2097,"dataGaName":2098,"dataGaLocation":2052},"https://status.gitlab.com/","status",{"text":2100,"config":2101},"Nutzungsbedingungen",{"href":2102,"dataGaName":2103,"dataGaLocation":2052},"/terms/","terms of use",{"text":2105,"config":2106},"Datenschutzerklärung",{"href":2107,"dataGaName":2108,"dataGaLocation":2052},"/de-de/privacy/","privacy statement",{"text":2110,"config":2111},"Cookie-Einstellungen",{"dataGaName":2112,"dataGaLocation":2052,"id":2113,"isOneTrustButton":195},"cookie preferences","ot-sdk-btn",{"title":1657,"links":2115,"subMenu":2124},[2116,2120],{"text":2117,"config":2118},"DevSecOps-Plattform",{"href":1639,"dataGaName":2119,"dataGaLocation":2052},"devsecops platform",{"text":2121,"config":2122},"KI-unterstützte Entwicklung",{"href":1646,"dataGaName":2123,"dataGaLocation":2052},"ai-assisted development",[2125],{"title":2126,"links":2127},"Themen",[2128,2132,2137,2142,2147,2152,2157,2162],{"text":1601,"config":2129},{"href":2130,"dataGaName":2131,"dataGaLocation":2052},"/de-de/topics/ci-cd/","cicd",{"text":2133,"config":2134},"GitOps",{"href":2135,"dataGaName":2136,"dataGaLocation":2052},"/de-de/topics/gitops/","gitops",{"text":2138,"config":2139},"DevOps",{"href":2140,"dataGaName":2141,"dataGaLocation":2052},"/de-de/topics/devops/","devops",{"text":2143,"config":2144},"Versionskontrolle",{"href":2145,"dataGaName":2146,"dataGaLocation":2052},"/de-de/topics/version-control/","version control",{"text":2148,"config":2149},"DevSecOps",{"href":2150,"dataGaName":2151,"dataGaLocation":2052},"/de-de/topics/devsecops/","devsecops",{"text":2153,"config":2154},"Cloud-nativ",{"href":2155,"dataGaName":2156,"dataGaLocation":2052},"/de-de/topics/cloud-native/","cloud native",{"text":2158,"config":2159},"KI für das Programmieren",{"href":2160,"dataGaName":2161,"dataGaLocation":2052},"/de-de/topics/devops/ai-for-coding/","ai for coding",{"text":2163,"config":2164},"Agentische KI",{"href":2165,"dataGaName":2166,"dataGaLocation":2052},"/de-de/topics/agentic-ai/","agentic ai",{"title":2168,"links":2169},"Lösungen",[2170,2173,2175,2180,2184,2187,2190,2193,2195,2197,2199,2204],{"text":1701,"config":2171},{"href":1696,"dataGaName":2172,"dataGaLocation":2052},"Application Security Testing",{"text":1688,"config":2174},{"href":1673,"dataGaName":1674,"dataGaLocation":2052},{"text":2176,"config":2177},"Agile Entwicklung",{"href":2178,"dataGaName":2179,"dataGaLocation":2052},"/de-de/solutions/agile-delivery/","agile delivery",{"text":2181,"config":2182},"SCM",{"href":1685,"dataGaName":2183,"dataGaLocation":2052},"source code management",{"text":1601,"config":2185},{"href":1678,"dataGaName":2186,"dataGaLocation":2052},"continuous integration & delivery",{"text":1727,"config":2188},{"href":1729,"dataGaName":2189,"dataGaLocation":2052},"value stream management",{"text":2133,"config":2191},{"href":2192,"dataGaName":2136,"dataGaLocation":2052},"/de-de/solutions/gitops/",{"text":1740,"config":2194},{"href":1743,"dataGaName":1744,"dataGaLocation":2052},{"text":1746,"config":2196},{"href":1749,"dataGaName":1750,"dataGaLocation":2052},{"text":1752,"config":2198},{"href":1755,"dataGaName":1756,"dataGaLocation":2052},{"text":2200,"config":2201},"Bildungswesen",{"href":2202,"dataGaName":2203,"dataGaLocation":2052},"/de-de/solutions/education/","education",{"text":2205,"config":2206},"Finanzdienstleistungen",{"href":2207,"dataGaName":2208,"dataGaLocation":2052},"/de-de/solutions/finance/","financial services",{"title":1763,"links":2210},[2211,2213,2215,2217,2220,2222,2225,2227,2229,2231,2233,2235,2237,2239],{"text":1776,"config":2212},{"href":1778,"dataGaName":1779,"dataGaLocation":2052},{"text":1781,"config":2214},{"href":1783,"dataGaName":1784,"dataGaLocation":2052},{"text":1786,"config":2216},{"href":1788,"dataGaName":1789,"dataGaLocation":2052},{"text":1791,"config":2218},{"href":1793,"dataGaName":2219,"dataGaLocation":2052},"docs",{"text":1814,"config":2221},{"href":1816,"dataGaName":1817,"dataGaLocation":2052},{"text":2223,"config":2224},"Neuerungen",{"href":1874,"dataGaName":1875,"dataGaLocation":2052},{"text":1809,"config":2226},{"href":1811,"dataGaName":1812,"dataGaLocation":2052},{"text":1828,"config":2228},{"href":1830,"dataGaName":1831,"dataGaLocation":2052},{"text":1836,"config":2230},{"href":1838,"dataGaName":1839,"dataGaLocation":2052},{"text":1841,"config":2232},{"href":1843,"dataGaName":1844,"dataGaLocation":2052},{"text":1846,"config":2234},{"href":1848,"dataGaName":1849,"dataGaLocation":2052},{"text":1851,"config":2236},{"href":1853,"dataGaName":1854,"dataGaLocation":2052},{"text":1856,"config":2238},{"href":1858,"dataGaName":1859,"dataGaLocation":2052},{"text":1861,"config":2240},{"href":1863,"dataGaName":1864,"dataGaLocation":2052},{"title":1877,"links":2242},[2243,2245,2247,2249,2251,2253,2258,2263,2265,2267,2269],{"text":1885,"config":2244},{"href":1887,"dataGaName":1879,"dataGaLocation":2052},{"text":1890,"config":2246},{"href":1892,"dataGaName":1893,"dataGaLocation":2052},{"text":1898,"config":2248},{"href":1900,"dataGaName":1901,"dataGaLocation":2052},{"text":1903,"config":2250},{"href":1905,"dataGaName":1906,"dataGaLocation":2052},{"text":1908,"config":2252},{"href":1910,"dataGaName":1911,"dataGaLocation":2052},{"text":2254,"config":2255},"Nachhaltigkeit",{"href":2256,"dataGaName":2257,"dataGaLocation":2052},"/sustainability/","Sustainability",{"text":2259,"config":2260},"Vielfalt, Inklusion und Zugehörigkeit",{"href":2261,"dataGaName":2262,"dataGaLocation":2052},"/de-de/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1913,"config":2264},{"href":1915,"dataGaName":1916,"dataGaLocation":2052},{"text":1923,"config":2266},{"href":1925,"dataGaName":1926,"dataGaLocation":2052},{"text":1928,"config":2268},{"href":1930,"dataGaName":1931,"dataGaLocation":2052},{"text":2270,"config":2271},"Transparenzerklärung zu moderner Sklaverei",{"href":2272,"dataGaName":2273,"dataGaLocation":2052},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":2275},[2276,2279,2282],{"text":2277,"config":2278},"Terms",{"href":2102,"dataGaName":2103,"dataGaLocation":2052},{"text":2280,"config":2281},"Cookies",{"dataGaName":2112,"dataGaLocation":2052,"id":2113,"isOneTrustButton":195},{"text":2283,"config":2284},"Datenschutz",{"href":2107,"dataGaName":2108,"dataGaLocation":2052},[2286],{"id":2287,"title":7,"body":1590,"config":2288,"content":2290,"description":1590,"extension":2294,"meta":2295,"navigation":195,"path":2296,"seo":2297,"stem":2298,"__hash__":2299},"blogAuthors/en-us/blog/authors/dov-hershkovitch.yml",{"template":2289},"BlogAuthor",{"name":7,"config":2291},{"headshot":2292,"ctfId":2293},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665628/Blog/Author%20Headshots/dhershkovitch-headshot.png","dhershkovitch","yml",{},"/en-us/blog/authors/dov-hershkovitch",{},"en-us/blog/authors/dov-hershkovitch","Iz4JuWpp9w9MyL2i-FC6CmJS1rnfmg76IL873W1AcMU",[2301,2309,2316],{"title":2302,"description":2303,"heroImage":2304,"category":1586,"date":2305,"authors":2306,"slug":2308,"externalUrl":1590},"DevOps Stack aufbauen: Häufige Fehler und Best Practices für moderne Toolchains","Ein DevOps Stack sollte mehr sein als eine Tool-Sammlung. Lerne, wie Teams häufige Fehler vermeiden und mit GitLab Toolchain-Komplexität reduzieren.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1775561395/bhe1as7ttjvzltxwgo5m.png","2026-08-07",[2307],"GitLab Germany Team","devops-stack",{"title":2310,"description":2311,"heroImage":2312,"category":1586,"date":2313,"authors":2314,"slug":2315,"externalUrl":1590},"Sechs Möglichkeiten, die DevOps Kosten zu senken, zu sparen und zu optimieren","Wir zeigen dir sechs Möglichkeiten, wie du deine DevOps Kosten senken kannst.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1775486753/cswmwtygkgkbdsibo09v.png","2026-07-20",[2307],"reduce-devops-costs",{"title":2317,"description":2318,"heroImage":2319,"category":1586,"date":2313,"authors":2320,"slug":2322,"externalUrl":1590},"Work Items automatisch zuweisen mit dem Trigger \"Work item created\"","Eine Schritt-für-Schritt-Anleitung zum neuen Trigger, der Work Items automatisch zuweist – skalierbare Triage ohne manuelles Eingreifen.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1773866173/vte9qh8rriznvyclhkes.png",[2321],"Cesar Saavedra","how-to-use-a-work-item-created-trigger",{"promotions":2324},[2325,2339,2350,2361],{"id":2326,"categories":2327,"header":2329,"text":2330,"button":2331,"image":2336},"ai-modernization",[2328],"ai","Hält KI, was uns versprochen wurde?","Das Quiz dauert maximal 5 Minuten.",{"text":2332,"config":2333},"Ermittle deinen KI-Reifegrad",{"href":2334,"dataGaName":2335,"dataGaLocation":1817},"/de-de/assessments/ai-modernization-assessment/","modernization assessment",{"config":2337},{"src":2338},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":2340,"categories":2341,"header":2342,"text":2330,"button":2343,"image":2347},"devops-modernization",[1586,2151],"Verwaltest du Tool-Chaos oder stellst du Innovationen bereit?",{"text":2344,"config":2345},"Ermittle deinen DevOps-Reifegrad",{"href":2346,"dataGaName":2335,"dataGaLocation":1817},"/de-de/assessments/devops-modernization-assessment/",{"config":2348},{"src":2349},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":2351,"categories":2352,"header":2353,"text":2330,"button":2354,"image":2358},"security-modernization",[1602],"Tauschst du Schnelligkeit gegen Sicherheit ein?",{"text":2355,"config":2356},"Ermittle deinen Sicherheitsreifegrad",{"href":2357,"dataGaName":2335,"dataGaLocation":1817},"/de-de/assessments/security-modernization-assessment/",{"config":2359},{"src":2360},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":2362,"paths":2363,"header":2366,"text":2367,"button":2368,"image":2373},"github-azure-migration",[2364,2365],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Ist dein Team bereit für den Umzug von GitHub nach Azure?","GitHub stellt bereits auf Azure um. Finde heraus, was das für dich bedeutet.",{"text":2369,"config":2370},"Erfahre, wie GitLab im Vergleich zu GitHub abschneidet",{"href":2371,"dataGaName":2372,"dataGaLocation":1817},"/de-de/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":2374},{"src":2349},{"header":2376,"blurb":2377,"button":2378,"secondaryButton":2383},"Beginne noch heute, schneller zu entwickeln","Entdecke, was dein Team mit der intelligenten Orchestrierungsplattform für DevSecOps erreichen kann.\n",{"text":2379,"config":2380},"Kostenlosen Test starten",{"href":2381,"dataGaName":1615,"dataGaLocation":2382},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/de-de/","feature",{"text":1940,"config":2384},{"href":1942,"dataGaName":1620,"dataGaLocation":2382},1786803739413]