[{"data":1,"prerenderedAt":707},["ShallowReactive",2],{"/de-de/blog/basics-of-gitlab-ci-updated/":3,"navigation-de-de":36,"banner-de-de":456,"footer-de-de":469,"Itzik Gan Baruch":679,"next-steps-de-de":692},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":26,"_id":29,"_type":30,"title":31,"_source":32,"_file":33,"_stem":34,"_extension":35},"/de-de/blog/basics-of-gitlab-ci-updated","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Grundlagen der GitLab-CI-Pipeline: Aufgaben sequenziell parallel oder ohne Reihenfolge ausführen","Neu in der Continuous Integration? Erfahre, wie du deine erste CI-Pipeline mit GitLab erstellst.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662061/Blog/Hero%20Images/cicdcover.png","https://about.gitlab.com/blog/basics-of-gitlab-ci-updated","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Grundlagen der GitLab-CI-Pipeline: Aufgaben sequenziell parallel oder ohne Reihenfolge ausführen\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2020-12-10\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22,"updatedDate":25},[18],"Itzik Gan Baruch","2020-12-10","Nehmen wir an, dass du nichts über [kontinuierliche Integration\n(CI)](/topics/ci-cd/) and [why it's\nneeded](/blog/how-to-keep-up-with-ci-cd-best-practices/) weißt\nund darüber, warum sie im Lebenszyklus der Softwareentwicklung benötigt\nwird.\n\n\n## Inhaltsverzeichnis\n\n- [Der erste Test in CI](#der-erste-test-in-ci)\n\n- [Ergebnisse von Builds zum Herunterladen\nbereitstellen](#ergebnisse-von-builds-zum-herunterladen-bereitstellen)\n\n- [Aufträge der Reihe nach ausführen](#aufträge-der-reihe-nach-ausführen)\n\n- [Welches Docker Image muss verwendet\nwerden?](#welches-docker-image-muss-verwendet-werden%3F)\n\n- [Umgang mit komplexen Szenarien](#umgang-mit-komplexen-szenarien)\n\n- [Umgang mit fehlender\nSoftware/Paketen](#umgang-mit-fehlender-softwarepaketen)\n\n- [Directed Acyclic Graphs: Schnellere und flexiblere\nPipelines](#directed-acyclic-graphs-schnellere-und-flexiblere-pipelines)\n\n- [Wie wertest du deine Pipeline\nauf?](#wie-wertest-du-deine-pipeline-auf%3F)\n  - [Automatisierte Tests in CI-Pipelines einbinden](#automatisierte-tests-in-ci-pipelines-einbinden)\n  - [Matrix-Builds](#matrix-builds)\n- [Unit-Tests](#unit-tests)\n  - [Was sind Unit-Tests?](#was-sind-unit-tests%3F)\n  - [Best Practices für Unit-Tests](#best-practices-für-unit-tests)\n    - [JUnit Test-Report](#junit-test-report)\n- [Strategien für Integrations- und\nEnd-to-End-Tests](#strategien-für-integrations--und-end-to-end-tests)\n\n- [Testumgebung](#testumgebung)\n\n- [Implementierung von Sicherheitsscans in\nCI-Pipelines](#implementierung-von-sicherheitsscans-in-ci-pipelines)\n  - [SAST und DAST-Integration](#sast-und-dast-integration)\n- [Zusammenfassung](#zusammenfassung)\n\n- [Beschreibungen der Keywords](#beschreibungen-der-keywords)\n\n\nStell dir vor, du arbeitest an einem Projekt, bei dem der gesamte Code aus\nzwei Textdateien besteht. Dabei ist es sehr wichtig, dass die Verkettung\ndieser beiden Dateien die Phrase „Hello world\" enthält.\n\n\nWenn das nicht der Fall ist, wird das gesamte Development-Team in diesem\nMonat nicht bezahlt. Ja, so ernst ist es!\n\n\nDer oder die verantwortliche Softwareentwickler(in) hat ein kleines Skript\ngeschrieben, das jedes Mal ausgeführt wird, wenn wir unseren Code an die\nKunden senden wollen.\n\n\nDer Code ist ziemlich komplex:\n\n\n```bash\n\ncat file1.txt file2.txt | grep -q \"Hello world\"\n\n```\n\n\nDas Problem ist, dass das Team aus 10 Entwickler(inne)n besteht. Da bleiben\nmenschliche Fehler nicht aus.\n\n\nVor einer Woche vergaß einer der Mitarbeiter(innen), das Skript auszuführen,\nund drei Kund(inn)en erhielten fehlerhafte Builds. Also hast du beschlossen,\ndieses Problem endgültig zu lösen. Glücklicherweise befindet sich der Code\nbereits auf GitLab, und du erinnerst dich, dass es eine [integrierte\nCI](/de-de/solutions/continuous-integration/) gibt. Zudem hast du auf einer\nKonferenz gehört, dass viele Entwickler(innen) eine CI verwenden, um Tests\ndurchzuführen...\n\n\n## Der erste Test in CI\n\n\nNach ein paar Minuten Suche und Lesen der Dokumentation scheint es, dass wir\nnur diese zwei Codezeilen benötigen, die wir in einer Datei namens\n.gitlab-ci.yml finden:\n\n\n```yaml\n\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n```\n\n\nWir übertragen die Zeilen, und siehe da– unser Build ist erfolgreich:\n\n\n![build\nsucceeded](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/build_succeeded.png)\n\n\nNun ändern wir in der zweiten Datei \"World\" zu \"Africa\" und prüfen, was\npassiert:\n\n\n![build\nfailed](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/build_failed.png)\n\n\nDer Build schlägt wie erwartet fehl!\n\n\nNun haben wir hier automatisierte Tests! GitLab CI führt unser Testskript\njedes Mal aus, wenn wir neuen Code in das Quellcode-Repository in der\nDevOps-Umgebung übertragen.\n\n\n**Hinweis:** Im obigen Beispiel gehen wir davon aus, dass file1.txt und\nfile2.txt auf dem Runner-Host vorhanden sind.\n\n\nUm dieses Beispiel in GitLab auszuführen, verwende den folgenden Code, der\nzunächst die Dateien erstellt und dann das Skript ausführt.\n\n\n```yaml\n\ntest:\n\nbefore_script:\n      - echo \"Hello \" > | tr -d \"\\n\" | > file1.txt\n      - echo \"world\" > file2.txt\nscript: cat file1.txt file2.txt | grep -q 'Hello world'\n\n```\n\n\nAus Gründen der Übersichtlichkeit gehen wir davon aus, dass diese Dateien\nauf dem Host vorhanden sind und werden sie in den folgenden Beispielen nicht\nerstellen.\n\n\n## Ergebnisse von Builds zum Herunterladen bereitstellen\n\n\nDie nächste Anforderung besteht darin, den Code zu paketieren, bevor wir ihn\nan unsere Kunden senden. Lass uns auch diesen Teil des\nSoftwareentwicklungsprozesses automatisieren!\n\n\nAlles, was wir machen müssen, ist, einen weiteren Job für CI zu definieren.\nNennen wir den Auftrag mal „Package\":\n\n\n```yaml\n\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  script: cat file1.txt file2.txt | gzip > package.gz\n```\n\n\nNun haben wir zwei Tabs:\n\n\n![Two tabs - generated from two\njobs](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/two_tabs.png)\n\n\nWir haben jedoch vergessen anzugeben, dass die neue Datei ein Build-Artefakt\nist, damit sie heruntergeladen werden kann. Wir können dies beheben, indem\nwir einen Abschnitt für Artifacts hinzufügen:\n\n\n```yaml\n\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  script: cat file1.txt file2.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\n\nChecking... it is there:\n\n\n![Checking the download\nbutton](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/artifacts.png)\n\n\nSo klappt's. Wir haben jedoch noch ein Problem zu lösen: Die Aufträge laufen\nparallel, aber wir wollen unsere Anwendung nicht paketieren, wenn unsere\nTests fehlschlagen.\n\n\n## Aufträge der Reihe nach ausführen\n\n\nDer Auftrag „Paket\" soll nur ausgeführt werden, wenn die Tests erfolgreich\nsind. Definieren wir die Reihenfolge, indem wir stages angeben:\n\n\n```yaml\n\nstages:\n  - test\n  - package\n\ntest:\n  stage: test\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  stage: package\n  script: cat file1.txt file2.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\n\nDas sollte funktionieren!\n\nAußerdem haben wir vergessen zu erwähnen, dass die Zusammenstellung (die in\nunserem Fall durch Verkettung dargestellt wird) eine Weile dauert, sodass\nwir sie nicht zweimal ausführen wollen. Definieren wir also einen separaten\nSchritt dafür:\n\n\n```yaml\n\nstages:\n  - compile\n  - test\n  - package\n\ncompile:\n  stage: compile\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n\ntest:\n  stage: test\n  script: cat compiled.txt | grep -q 'Hello world'\n\npackage:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\n\nLass uns jetzt auf unsere Artifacts an:\n\n\n![Unnecessary\nartifact](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/clean-artifacts.png)\n\n\nWir brauchen diese „Kompilierungsdatei\" nicht zum Herunterladen. Deshalb\nlassen wir unsere temporären Artefakte ablaufen, indem wir expire_in auf „20\nMinuten\" setzen:\n\n\n```yaml\n\ncompile:\n  stage: compile\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n    expire_in: 20 minutes\n```\n\n\nJetzt sieht unsere Konfiguration ziemlich beeindruckend aus:\n\n\n- Wir haben drei aufeinanderfolgende Phasen zum Kompilieren, Testen und\nPaketieren unserer Anwendung.\n\n- Wir übergeben die kompilierte Anwendung an die nächsten Stufen, damit die\nKompilierung nicht zweimal ausgeführt werden muss (und somit schneller\nläuft).\n\n- Wir speichern eine paketierte Version unserer Anwendung in\nBuild-Artefakten für die weitere Verwendung.\n\n\n## Welches Docker Image muss verwendet werden?\n\n\nEs scheint, dass unsere Builds immer noch langsam sind. Werfen wir einen\nBlick auf die Protokolle.\n\n\n![ruby3.1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/ruby-31.png)\n\n\nWas ist Ruby 3.1?\n\n\nGitLab.com verwendet Docker-Images, um unsere\n[Builds](/blog/shared-runners/) auszuführen, und\n[standardmäßig](https://docs.gitlab.com/ee/user/gitlab_com/#shared-runners)\nwird das [`ruby:3.1`](https://hub.docker.com/_/ruby/)-Image verwendet.\nDieses Image enthält natürlich viele Pakete, die wir nicht brauchen. Nach\neiner Minute des Googlens finden wir heraus, dass es ein Image namens\n[`alpine`](https://hub.docker.com/_/alpine/) gibt, das ein fast leeres\nLinux-Image ist.\n\n\nWir geben also explizit an, dass wir dieses Image verwenden wollen, indem\nwir image: alpine` to `.gitlab-ci.yml`.\n\n\nWir haben so drei Minuten gespart:\n\n\n![Build speed\nimproved](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/speed.png)\n\n\nEs sieht so aus, als gäbe es viele öffentliche Images:\n\n- [mysql](https://hub.docker.com/_/mysql/)\n\n- [Python](https://hub.docker.com/_/python/)\n\n- [Java](https://hub.docker.com/_/java/)\n\n- [php](https://hub.docker.com/_/php/)\n\n\nWir können also einfach eines für unseren Technologie-Stack nehmen. Es ist\nsinnvoll, ein Image anzugeben, das keine zusätzliche Software enthält, da\ndies die Downloadzeit verringert.\n\n\n## Umgang mit komplexen Szenarien\n\n\nNehmen wir nun aber an, wir haben neue Kund(inn)en, die möchten, dass wir\nunsere Anwendung in ein .iso-Image statt in ein .gz-Image packen. ISO-Images\nkönnen mit dem Befehl\n[mkisofs](http://www.w3big.com/linux/linux-comm-mkisofs.html) erstellt\nwerden. Da CI die ganze Arbeit erledigt, können wir einfach einen weiteren\nJob hinzufügen. Darauf basierend sollte unsere Konfiguration so aussehen:\n\n\n```yaml\n\nimage: alpine\n\n\nstages:\n  - compile\n  - test\n  - package\n\n# ... \"compile\" and \"test\" jobs are skipped here for the sake of compactness\n\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\n\nBeachte, dass die Auftragsnamen nicht unbedingt gleich sein sollten. Wären\nsie identisch, wäre es nicht möglich, die Aufträge innerhalb derselben Phase\ndes Softwareentwicklungsprozesses parallel laufen zu lassen. Sollte es daher\ndoch mal vorkommen, kannst du das getrost als Zufall betrachten.\n\n\nWie dem auch sei, zurück zu unserem Job, da läuft es nicht recht rund – der\nBuild schlägt fehl:\n\n\n![Failed build because of missing\nmkisofs](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/mkisofs.png)\n\n\n`mkisofs` ist nicht im `alpine` Image mit dabei, also müssenw ir es erstmal\ninstallieren.\n\n\n## Umgang mit fehlender Software/Paketen\n\n\nLaut der [Alpine Linux\nwebsite](https://pkgs.alpinelinux.org/contents?file=mkisofs&path=&name=&branch=edge&repo=&arch=)\nist mkisofs Teil der Pakete xorriso und cdrkit. Dies sind die Befehle, die\nwir ausführen müssen, um ein Paket zu installieren:\n\n\n```bash\n\necho \"ipv6\" >> /etc/modules  # enable networking\n\napk update                   # update packages list\n\napk add xorriso              # install package\n\n```\n\n\nFür CI sind dies die gleichen Befehle wie für alle anderen. Die vollständige\nListe der Befehle, die wir dem Skriptabschnitt übergeben müssen, sollte wie\nfolgt aussehen:\n\n\n```yml\n\nscript:\n\n- echo \"ipv6\" >> /etc/modules\n\n- apk update\n\n- apk add xorriso\n\n- mkisofs -o ./packaged.iso ./compiled.txt\n\n```\n\n\nUm es jedoch semantisch korrekt zu machen, sollten wir die Befehle, die sich\nauf die Paketinstallation beziehen, in before_script unterbringen. Beachte,\ndass, wenn du before_script auf der obersten Ebene einer Konfiguration\nverwendest, die Befehle vor allen Aufträgen ausgeführt werden. In unserem\nFall wollen wir nur, dass sie vor einem bestimmten Auftrag ausgeführt\nwerden.\n\n\n## Directed Acyclic Graphs: Schnellere und flexiblere Pipelines\n\n\nWir haben die Stufen so definiert, dass die Paketaufgaben nur ausgeführt\nwerden, wenn die Tests bestanden wurden. Was aber, wenn wir die\nPhasenabfolge ein wenig aufbrechen und einige Aufträge früher ausführen\nwollen, auch wenn sie in einer späteren Phase definiert sind? In einigen\nFällen kann die herkömmliche Phasenabfolge die Gesamtausführungszeit der\nPipeline verlangsamen.\n\n\nStell dir vor, dass unsere Testphase einige umfangreichere Tests enthält,\nderen Ausführung viel Zeit in Anspruch nimmt und diese Tests nicht unbedingt\nmit den Paketaufgaben zusammenhängen. In diesem Fall wäre es effizienter,\nwenn die Paketaufgaben nicht auf den Abschluss dieser Tests warten müssten,\nbevor sie beginnen können. An dieser Stelle kommen Directed Acyclic Graphs\n(DAG) ins Spiel: Um die Phasenreihenfolge für bestimmte Aufträge zu\nunterbrechen, kannst du Abhängigkeiten von Aufgaben definieren, die die\nreguläre Phasenreihenfolge übergehen.\n\n\nGitLab verfügt über ein spezielles Keyword „needs\", das Abhängigkeiten\nzwischen Aufträgen schafft und es ermöglicht, Aufträge früher auszuführen,\nsobald ihre abhängigen Aufträge abgeschlossen sind.\n\n\nIm folgenden Beispiel werden die Paketaufgaben ausgeführt, sobald der\nTestjob abgeschlossen ist. Wenn also in Zukunft jemand weitere Tests in der\nTestphase hinzufügt, beginnen die Paketjobs zu laufen, bevor die neuen\nTestjobs abgeschlossen sind\n\n\n```yaml\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  before_script:\n  - echo \"ipv6\" >> /etc/modules\n  - apk update\n  - apk add xorriso\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\n\nUnsere finale Version von: `.gitlab-ci.yml`:\n\n\n```yaml\n\nimage: alpine\n\n\nstages:\n  - compile\n  - test\n  - package\n\ncompile:\n  stage: compile\n  before_script:\n      - echo \"Hello  \" | tr -d \"\\n\" > file1.txt\n      - echo \"world\" > file2.txt\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n    expire_in: 20 minutes\n\ntest:\n  stage: test\n  script: cat compiled.txt | grep -q 'Hello world'\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  before_script:\n  - echo \"ipv6\" >> /etc/modules\n  - apk update\n  - apk add xorriso\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\n\nWir haben gerade eine Pipeline erstellt! Wir haben drei sequenzielle Stufen,\ndie Aufträge `pack-gz` und `pack-iso` innerhalb der package-Stufe laufen\nparallel:\n\n\n![Pipelines\nillustration](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/pipeline.png)\n\n\n## Wie wertest du deine Pipeline auf?\n\n\nSo kannst du deine Pipeline aufwerten.\n\n\n### Automatisierte Tests in CI-Pipelines einbinden\n\n\nEine wichtige Regel der DevOps-Strategie für die Softwareentwicklung besteht\ndarin, wirklich großartige Anwendungen mit erstaunlicher Benutzererfahrung\nzu entwickeln. Fügen wir also einige Tests in unsere CI-Pipeline ein, um\nFehler frühzeitig im gesamten Prozess zu erkennen. Auf diese Weise können\nwir Probleme beheben, bevor sie zu groß werden und bevor wir an einem neuen\nProjekt weiterarbeiten.\n\n\nGitLab macht uns das Leben leichter, indem es fertige Vorlagen für\nverschiedene [Tests](https://docs.gitlab.com/ee/ci/testing/) anbietet.\nAlles, was wir tun müssen, ist, diese Vorlagen in unsere CI-Konfiguration\naufzunehmen.\n\n\nIn diesem Beispiel schließen wir auch\n[Accessibility-Tests](https://docs.gitlab.com/ee/ci/testing/accessibility_testing.html)\nein:\n\n\n```yaml\n\nstages:\n  - accessibility\n\nvariables:\n  a11y_urls: \"https://about.gitlab.com https://www.example.com\"\n\ninclude:\n  - template: \"Verify/Accessibility.gitlab-ci.yml\"\n```\n\n\nPasse die Variable a11y_urls an, um die URLs der Webseiten aufzulisten, die\nmit [Pa11y](https://pa11y.org/) und der\n[Codequalität](https://docs.gitlab.com/ee/ci/testing/code_quality.html)\ngetestet werden sollen.\n\n\n```yaml\n   include:\n   - template: Jobs/Code-Quality.gitlab-ci.yml\n```\n\n\nMit GitLab kannst du den Testbericht direkt im Widget-Bereich der\nZusammenführungsanforderung sehen. Wenn du die Codeüberprüfung, den\nPipelinestatus und die Testergebnisse an einem Ort hast, wird alles\nreibungsloser und effizienter.\n\n\n![Accessibility\nreport](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_10.56.41.png)\n\n\u003Ccenter>\u003Ci>Widget für die Zusammenführung von\nAccessibility-Anfragen\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n\n![Code quality widget in\nMR](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_11.00.25.png)\n\n\u003Ccenter>\u003Ci>Widget für Zusammenführungsanfragen in Codequalität\u003C/i>\u003C/center>\n\n\n### Matrix-Builds\n\n\nIn einigen Fällen müssen wir unsere Anwendung in verschiedenen\nKonfigurationen, Betriebssystemversionen, Programmiersprachenversionen usw.\ntesten. In diesen Fällen verwenden wir den\n[parallel:matrix](https://docs.gitlab.com/ee/ci/yaml/#parallelmatrix)-Build,\num unsere Anwendung in verschiedenen Kombinationen parallel mit einer\nJob-Konfiguration zu testen. In diesem Artikel werden wir unseren Code mit\nverschiedenen Python-Versionen unter Verwendung des Schlüsselworts matrix\ntesten.\n\n\n```yaml\n\npython-req:\n  image: python:$VERSION\n  stage: lint\n  script:\n    - pip install -r requirements_dev.txt\n    - chmod +x ./build_cpp.sh\n    - ./build_cpp.sh\n  parallel:\n    matrix:\n      - VERSION: ['3.8', '3.9', '3.10', '3.11']   # https://hub.docker.com/_/python\n```\n\n\nWährend der Pipeline-Ausführung wird dieser Auftrag viermal parallel\nausgeführt, wobei jedes Mal ein anderes Python-Image verwendet wird (siehe\nunten):\n\n\n![Matrix job\nrunning](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_11.12.48.png)\n\n\n### Unit-Tests\n\n\n#### Was sind Unit-Tests?\n\n\nUnit-Tests sind kleine, gezielte Tests, die einzelne Komponenten oder\nFunktionen von Software prüfen, um sicherzustellen, dass sie wie erwartet\nfunktionieren. Sie sind wichtig, um Fehler in einem frühen Stadium des\nSoftwareentwicklungsprozesses aufzuspüren und zu überprüfen, ob jeder Teil\ndes Codes für sich genommen korrekt funktioniert.\n\n\nBeispiel: Stell dir vor, du entwickelst eine Taschenrechner-App. Ein\nUnit-Test für die Additionsfunktion würde prüfen, ob 2 + 2 gleich 4 ist.\nWenn dieser Test erfolgreich ist, bestätigt er, dass die Additionsfunktion\nkorrekt funktioniert.\n\n\n#### Best Practices für Unit-Tests\n\n\nWenn die Tests fehlschlagen, schlägt die Pipeline fehl und die Benutzer\nwerden benachrichtigt. Entwickler(innen) müssen die Auftragsprotokolle, die\nin der Regel Tausende von Zeilen enthalten, überprüfen und feststellen, wo\ndie Tests fehlgeschlagen sind, um sie zu korrigieren. Diese Prüfung ist\nzeitaufwendig und ineffizient.\n\n\nDu kannst deinen Auftrag so konfigurieren, dass er\n[Unit-Test-Berichte](https://docs.gitlab.com/ee/ci/testing/unit_test_reports.html)\nverwendet. GitLab zeigt die Berichte in der Zusammenführungsanforderung und\nauf der Detailseite der Pipeline an, sodass du den Fehler einfacher und\nschneller identifizieren kannst, ohne das gesamte Protokoll überprüfen zu\nmüssen.\n\n\n##### JUnit Test-Report\n\n\nDies ist ein beispielhafter JUnit Test-Report:\n\n\n![pipelines JUnit test report v13\n10](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674097/Blog/Content%20Images/pipelines_junit_test_report_v13_10.png){:\n.shadow.center}\n\n\n### Strategien für Integrations- und End-to-End-Tests\n\n\nZusätzlich zu unserer regulären Entwicklungsroutine ist es sehr wichtig,\neine spezielle Pipeline nur für Integrations- und End-to-End-Tests\neinzurichten. Damit wird überprüft, ob alle verschiedenen Teile unseres\nCodes reibungslos zusammenarbeiten, einschließlich der\n[Microservices](https://about.gitlab.com/topics/microservices/), der\nUI-Tests und aller anderen Komponenten.\n\n\nWir führen diese Tests jede\n[Nacht](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) durch. Wir\nkönnen es so einrichten, dass die Ergebnisse automatisch an einen speziellen\n[Slack](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html#notification-events)-Kanal\ngesendet werden. Auf diese Weise können die Entwickler(innen), wenn sie am\nnächsten Tag kommen, schnell alle Probleme erkennen. Es geht darum, Probleme\nfrühzeitig zu erkennen und zu beheben!\n\n\n### Testumgebung\n\n\nFür einige der Tests benötigen wir möglicherweise eine Testumgebung, um\nunsere Anwendungen ordnungsgemäß zu testen. Mit GitLab CI/CD können wir die\nBereitstellung von Testumgebungen automatisieren und so eine Menge Zeit\nsparen. Da es in diesem Blog hauptsächlich um CI geht, werde ich nicht näher\ndarauf eingehen, aber du kannst diesen Abschnitt in der\n[GitLab-Dokumentation](https://docs.gitlab.com/ee/topics/release_your_application.html)\nnachlesen.\n\n\n## Implementierung von Sicherheitsscans in CI-Pipelines\n\n\nFolgend siehst du die Möglichkeiten zur Implementierung von Sicherheitsscans\nin CI-Pipelines.\n\n\n### SAST und DAST-Integration\n\n\nWir legen großen Wert darauf, dass unser Code sicher ist. Wenn unsere\nletzten Änderungen Schwachstellen aufweisen, wollen wir das so schnell wie\nmöglich wissen. Sicherheitsscans sind hier eine sinnvolle Lösung und wir\nempfehlen dir, sie auch in deine Pipeline aufzunehmen. Sie überprüfen den\nCode bei jeder Übertragung und warnen dich vor möglichen Risiken. Wir haben\neine Produktübersicht zusammengestellt, die dich durch das Hinzufügen von\nScans, einschließlich statischer Anwendungssicherheitstests\n([SAST](https://docs.gitlab.com/ee/user/application_security/sast/)) und\ndynamischer Anwendungssicherheitstests\n([DAST](https://docs.gitlab.com/ee/user/application_security/dast/)), zu\ndeiner CI-Pipeline führt.\n\n\n__Klicke__ auf das Bild unten, um zur Übersicht zu gelangen.\n\n\n[![Scans product\ntour](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-14_at_13.44.42.png)](https://gitlab.navattic.com/gitlab-scans)\n\n\nAußerdem können wir mithilfe von KI noch tiefer in Schwachstellen eindringen\nund Vorschläge zu ihrer Behebung erhalten.\n\n\nWeitere Informationen findest du in dieser Demo.\n\n\n[![product tour explain vulnerability\n](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-14_at_13.50.24.png)](https://tech-marketing.gitlab.io/static-demos/pt-explain-vulnerability.html)\n\n\n## Zusammenfassung\n\n\nEs gibt noch viel mehr zu erläutern, aber lass uns hier erst einmal\naufhören.\n\nAlle Beispiele sind bewusst einfach gehalten, um das Konzept GitLab CI\nvorzustellen, ohne die Dinge zu verkomplizieren. Fassen wir zusammen, was\nwir gelernt haben:\n\n\n1. Um Arbeit an GitLab CI zu delegieren, solltest du einen oder mehrere\n[Jobs](https://docs.gitlab.com/ee/ci/jobs/) in.gitlab-ci.yml. definieren.\n\n2. Jobs sollten Namen haben – also denk dir was Gutes aus! Jeder Auftrag\nenthält eine Reihe von Regeln und Anweisungen für GitLab CI, die durch\nspezielle Schlüsselwörter definiert sind.\n\n3. Aufträge können nacheinander, parallel oder ungeordnet über\n[DAG](https://docs.gitlab.com/ee/ci/directed_acyclic_graph/index.html)\nausgeführt werden.\n\n4. Du kannst Dateien zwischen Aufträgen weitergeben und sie in\nBuild-Artefakten speichern, sodass sie über die Schnittstelle\nheruntergeladen werden können.\n\n5. Du kannst Dateien zwischen Aufträgen weitergeben und sie in\nBuild-Artefakten speichern, sodass sie über die Schnittstelle\nheruntergeladen werden können.\n\n\nNachstehend findest du eine genauere Beschreibung der von uns verwendeten\nBegriffe und Schlüsselwörter sowie Links zu den entsprechenden Dokumenten.\n\n\n### Beschreibungen der Keywords\n\n\n{: #keywords}\n\n\n| Keyword/term       | Beschreibung |\n\n|---------------|--------------------|\n\n| [.gitlab-ci.yml](https://docs.gitlab.com/ee/ci/yaml/) | Datei mit allen\nDefinitionen dazu, wie dein Projekt aufgebaut sein sollte |\n\n| [script](https://docs.gitlab.com/ee/ci/yaml/#script)        | Definiert\nein Shell-Script, das ausgeführt werden soll |\n\n| [before_script](https://docs.gitlab.com/ee/ci/yaml/#before_script) | Wird\nverwendet, um den Befehl zu definieren, der vor (allen) Aufträgen ausgeführt\nwerden soll |\n\n|\n[image](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-image)\n| Definiert das zu verwendende Docker-Image |\n\n| [stages](https://docs.gitlab.com/ee/ci/yaml/#stages)         | Legt eine\nPipelinestufe fest (Standard: test) |\n\n| [artifacts](https://docs.gitlab.com/ee/ci/yaml/#artifacts)     | Definiert\neine Liste von Build-Artifacts |\n\n|\n[artifacts:expire_in](https://docs.gitlab.com/ee/ci/yaml/#artifactsexpire_in)\n| Wird verwendet, um hochgeladene Artifacts nach der angegebenen Zeit zu\nlöschen |\n\n| [needs](https://docs.gitlab.com/ee/ci/yaml/#needs) | Dient zur Definition\nvon Abhängigkeiten zwischen Aufträgen und ermöglicht die Ausführung von\nAufträgen außerhalb der Reihenfolge |\n\n| [pipelines](https://about.gitlab.com/topics/ci-cd/cicd-pipeline/) | Eine\nPipeline ist eine Gruppe von Builds, die stufenweise (Batches) ausgeführt\nwerden |\n","engineering",[23,24],"CI","tutorial","2025-05-16",{"slug":27,"featured":6,"template":28},"basics-of-gitlab-ci-updated","BlogPost","content:de-de:blog:basics-of-gitlab-ci-updated.yml","yaml","Basics Of Gitlab Ci Updated","content","de-de/blog/basics-of-gitlab-ci-updated.yml","de-de/blog/basics-of-gitlab-ci-updated","yml",{"_path":37,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":39,"_id":452,"_type":30,"title":453,"_source":32,"_file":454,"_stem":455,"_extension":35},"/shared/de-de/main-navigation","de-de",{"logo":40,"freeTrial":45,"sales":50,"login":55,"items":60,"search":393,"minimal":429,"duo":443},{"config":41},{"href":42,"dataGaName":43,"dataGaLocation":44},"/de-de/","gitlab logo","header",{"text":46,"config":47},"Kostenlose Testversion anfordern",{"href":48,"dataGaName":49,"dataGaLocation":44},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":51,"config":52},"Vertrieb kontaktieren",{"href":53,"dataGaName":54,"dataGaLocation":44},"/de-de/sales/","sales",{"text":56,"config":57},"Anmelden",{"href":58,"dataGaName":59,"dataGaLocation":44},"https://gitlab.com/users/sign_in/","sign in",[61,105,204,209,314,374],{"text":62,"config":63,"cards":65,"footer":88},"Plattform",{"dataNavLevelOne":64},"platform",[66,72,80],{"title":62,"description":67,"link":68},"Die umfassendste KI-basierte DevSecOps-Plattform",{"text":69,"config":70},"Erkunde unsere Plattform",{"href":71,"dataGaName":64,"dataGaLocation":44},"/de-de/platform/",{"title":73,"description":74,"link":75},"GitLab Duo (KI)","Entwickle Software schneller mit KI in jeder Phase der Entwicklung",{"text":76,"config":77},"Lerne GitLab Duo kennen",{"href":78,"dataGaName":79,"dataGaLocation":44},"/de-de/gitlab-duo/","gitlab duo ai",{"title":81,"description":82,"link":83},"Gründe, die für GitLab sprechen","10 Gründe, warum Unternehmen sich für GitLab entscheiden",{"text":84,"config":85},"Mehr erfahren",{"href":86,"dataGaName":87,"dataGaLocation":44},"/de-de/why-gitlab/","why gitlab",{"title":89,"items":90},"Erste Schritte mit",[91,96,101],{"text":92,"config":93},"Platform Engineering",{"href":94,"dataGaName":95,"dataGaLocation":44},"/de-de/solutions/platform-engineering/","platform engineering",{"text":97,"config":98},"Entwicklererfahrung",{"href":99,"dataGaName":100,"dataGaLocation":44},"/de-de/developer-experience/","Developer experience",{"text":102,"config":103},"MLOps",{"href":104,"dataGaName":102,"dataGaLocation":44},"/de-de/topics/devops/the-role-of-ai-in-devops/",{"text":106,"left":107,"config":108,"link":110,"lists":114,"footer":186},"Produkt",true,{"dataNavLevelOne":109},"solutions",{"text":111,"config":112},"Alle Lösungen anzeigen",{"href":113,"dataGaName":109,"dataGaLocation":44},"/de-de/solutions/",[115,141,164],{"title":116,"description":117,"link":118,"items":123},"Automatisierung","CI/CD und Automatisierung zur Beschleunigung der Bereitstellung",{"config":119},{"icon":120,"href":121,"dataGaName":122,"dataGaLocation":44},"AutomatedCodeAlt","/de-de/solutions/delivery-automation/","automated software delivery",[124,128,132,137],{"text":125,"config":126},"CI/CD",{"href":127,"dataGaLocation":44,"dataGaName":125},"/de-de/solutions/continuous-integration/",{"text":129,"config":130},"KI-unterstützte Entwicklung",{"href":78,"dataGaLocation":44,"dataGaName":131},"AI assisted development",{"text":133,"config":134},"Quellcodeverwaltung",{"href":135,"dataGaLocation":44,"dataGaName":136},"/de-de/solutions/source-code-management/","Source Code Management",{"text":138,"config":139},"Automatisierte Softwarebereitstellung",{"href":121,"dataGaLocation":44,"dataGaName":140},"Automated software delivery",{"title":142,"description":143,"link":144,"items":149},"Sicherheit","Entwickle schneller, ohne die Sicherheit zu gefährden",{"config":145},{"href":146,"dataGaName":147,"dataGaLocation":44,"icon":148},"/de-de/solutions/security-compliance/","security and compliance","ShieldCheckLight",[150,155,160],{"text":151,"config":152},"Application Security Testing",{"href":153,"dataGaName":154,"dataGaLocation":44},"/solutions/application-security-testing/","Application security testing",{"text":156,"config":157},"Schutz der Software-Lieferkette",{"href":158,"dataGaLocation":44,"dataGaName":159},"/de-de/solutions/supply-chain/","Software supply chain security",{"text":161,"config":162},"Software Compliance",{"href":163,"dataGaName":161,"dataGaLocation":44},"/solutions/software-compliance/",{"title":165,"link":166,"items":171},"Bewertung",{"config":167},{"icon":168,"href":169,"dataGaName":170,"dataGaLocation":44},"DigitalTransformation","/de-de/solutions/visibility-measurement/","visibility and measurement",[172,176,181],{"text":173,"config":174},"Sichtbarkeit und Bewertung",{"href":169,"dataGaLocation":44,"dataGaName":175},"Visibility and Measurement",{"text":177,"config":178},"Wertstrommanagement",{"href":179,"dataGaLocation":44,"dataGaName":180},"/de-de/solutions/value-stream-management/","Value Stream Management",{"text":182,"config":183},"Analysen und Einblicke",{"href":184,"dataGaLocation":44,"dataGaName":185},"/de-de/solutions/analytics-and-insights/","Analytics and insights",{"title":187,"items":188},"GitLab für",[189,194,199],{"text":190,"config":191},"Enterprise",{"href":192,"dataGaLocation":44,"dataGaName":193},"/de-de/enterprise/","enterprise",{"text":195,"config":196},"Kleinunternehmen",{"href":197,"dataGaLocation":44,"dataGaName":198},"/de-de/small-business/","small business",{"text":200,"config":201},"den öffentlichen Sektor",{"href":202,"dataGaLocation":44,"dataGaName":203},"/de-de/solutions/public-sector/","public sector",{"text":205,"config":206},"Preise",{"href":207,"dataGaName":208,"dataGaLocation":44,"dataNavLevelOne":208},"/de-de/pricing/","pricing",{"text":210,"config":211,"link":213,"lists":217,"feature":301},"Ressourcen",{"dataNavLevelOne":212},"resources",{"text":214,"config":215},"Alle Ressourcen anzeigen",{"href":216,"dataGaName":212,"dataGaLocation":44},"/de-de/resources/",[218,251,273],{"title":219,"items":220},"Erste Schritte",[221,226,231,236,241,246],{"text":222,"config":223},"Installieren",{"href":224,"dataGaName":225,"dataGaLocation":44},"/de-de/install/","install",{"text":227,"config":228},"Kurzanleitungen",{"href":229,"dataGaName":230,"dataGaLocation":44},"/de-de/get-started/","quick setup checklists",{"text":232,"config":233},"Lernen",{"href":234,"dataGaLocation":44,"dataGaName":235},"https://university.gitlab.com/","learn",{"text":237,"config":238},"Produktdokumentation",{"href":239,"dataGaName":240,"dataGaLocation":44},"https://docs.gitlab.com/","product documentation",{"text":242,"config":243},"Best-Practice-Videos",{"href":244,"dataGaName":245,"dataGaLocation":44},"/de-de/getting-started-videos/","best practice videos",{"text":247,"config":248},"Integrationen",{"href":249,"dataGaName":250,"dataGaLocation":44},"/de-de/integrations/","integrations",{"title":252,"items":253},"Entdecken",[254,259,263,268],{"text":255,"config":256},"Kundenerfolge",{"href":257,"dataGaName":258,"dataGaLocation":44},"/de-de/customers/","customer success stories",{"text":260,"config":261},"Blog",{"href":262,"dataGaName":5,"dataGaLocation":44},"/de-de/blog/",{"text":264,"config":265},"Remote",{"href":266,"dataGaName":267,"dataGaLocation":44},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":269,"config":270},"TeamOps",{"href":271,"dataGaName":272,"dataGaLocation":44},"/de-de/teamops/","teamops",{"title":274,"items":275},"Vernetzen",[276,281,286,291,296],{"text":277,"config":278},"GitLab-Services",{"href":279,"dataGaName":280,"dataGaLocation":44},"/de-de/services/","services",{"text":282,"config":283},"Community",{"href":284,"dataGaName":285,"dataGaLocation":44},"/community/","community",{"text":287,"config":288},"Forum",{"href":289,"dataGaName":290,"dataGaLocation":44},"https://forum.gitlab.com/","forum",{"text":292,"config":293},"Veranstaltungen",{"href":294,"dataGaName":295,"dataGaLocation":44},"/events/","events",{"text":297,"config":298},"Partner",{"href":299,"dataGaName":300,"dataGaLocation":44},"/de-de/partners/","partners",{"backgroundColor":302,"textColor":303,"text":304,"image":305,"link":309},"#2f2a6b","#fff","Perspektiven für die Softwareentwicklung der Zukunft",{"altText":306,"config":307},"the source promo card",{"src":308},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":310,"config":311},"Lies die News",{"href":312,"dataGaName":313,"dataGaLocation":44},"/de-de/the-source/","the source",{"text":315,"config":316,"lists":318},"Unternehmen",{"dataNavLevelOne":317},"company",[319],{"items":320},[321,326,332,334,339,344,349,354,359,364,369],{"text":322,"config":323},"Über",{"href":324,"dataGaName":325,"dataGaLocation":44},"/de-de/company/","about",{"text":327,"config":328,"footerGa":331},"Karriere",{"href":329,"dataGaName":330,"dataGaLocation":44},"/jobs/","jobs",{"dataGaName":330},{"text":292,"config":333},{"href":294,"dataGaName":295,"dataGaLocation":44},{"text":335,"config":336},"Geschäftsführung",{"href":337,"dataGaName":338,"dataGaLocation":44},"/company/team/e-group/","leadership",{"text":340,"config":341},"Team",{"href":342,"dataGaName":343,"dataGaLocation":44},"/company/team/","team",{"text":345,"config":346},"Handbuch",{"href":347,"dataGaName":348,"dataGaLocation":44},"https://handbook.gitlab.com/","handbook",{"text":350,"config":351},"Investor Relations",{"href":352,"dataGaName":353,"dataGaLocation":44},"https://ir.gitlab.com/","investor relations",{"text":355,"config":356},"Trust Center",{"href":357,"dataGaName":358,"dataGaLocation":44},"/de-de/security/","trust center",{"text":360,"config":361},"AI Transparency Center",{"href":362,"dataGaName":363,"dataGaLocation":44},"/de-de/ai-transparency-center/","ai transparency center",{"text":365,"config":366},"Newsletter",{"href":367,"dataGaName":368,"dataGaLocation":44},"/company/contact/","newsletter",{"text":370,"config":371},"Presse",{"href":372,"dataGaName":373,"dataGaLocation":44},"/press/","press",{"text":375,"config":376,"lists":377},"Kontakt",{"dataNavLevelOne":317},[378],{"items":379},[380,383,388],{"text":51,"config":381},{"href":53,"dataGaName":382,"dataGaLocation":44},"talk to sales",{"text":384,"config":385},"Support",{"href":386,"dataGaName":387,"dataGaLocation":44},"/support/","get help",{"text":389,"config":390},"Kundenportal",{"href":391,"dataGaName":392,"dataGaLocation":44},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":394,"login":395,"suggestions":402},"Schließen",{"text":396,"link":397},"Um Repositories und Projekte zu durchsuchen, melde dich an bei",{"text":398,"config":399},"gitlab.com",{"href":58,"dataGaName":400,"dataGaLocation":401},"search login","search",{"text":403,"default":404},"Vorschläge",[405,408,413,415,420,425],{"text":73,"config":406},{"href":78,"dataGaName":407,"dataGaLocation":401},"GitLab Duo (AI)",{"text":409,"config":410},"Code Suggestions (KI)",{"href":411,"dataGaName":412,"dataGaLocation":401},"/de-de/solutions/code-suggestions/","Code Suggestions (AI)",{"text":125,"config":414},{"href":127,"dataGaName":125,"dataGaLocation":401},{"text":416,"config":417},"GitLab auf AWS",{"href":418,"dataGaName":419,"dataGaLocation":401},"/de-de/partners/technology-partners/aws/","GitLab on AWS",{"text":421,"config":422},"GitLab auf Google Cloud",{"href":423,"dataGaName":424,"dataGaLocation":401},"/de-de/partners/technology-partners/google-cloud-platform/","GitLab on Google Cloud",{"text":426,"config":427},"Warum GitLab?",{"href":86,"dataGaName":428,"dataGaLocation":401},"Why GitLab?",{"freeTrial":430,"mobileIcon":435,"desktopIcon":440},{"text":431,"config":432},"Kostenlos testen",{"href":433,"dataGaName":49,"dataGaLocation":434},"https://gitlab.com/-/trials/new/","nav",{"altText":436,"config":437},"GitLab-Symbol",{"src":438,"dataGaName":439,"dataGaLocation":434},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":436,"config":441},{"src":442,"dataGaName":439,"dataGaLocation":434},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"freeTrial":444,"mobileIcon":448,"desktopIcon":450},{"text":445,"config":446},"Erfahre mehr über GitLab Duo",{"href":78,"dataGaName":447,"dataGaLocation":434},"gitlab duo",{"altText":436,"config":449},{"src":438,"dataGaName":439,"dataGaLocation":434},{"altText":436,"config":451},{"src":442,"dataGaName":439,"dataGaLocation":434},"content:shared:de-de:main-navigation.yml","Main Navigation","shared/de-de/main-navigation.yml","shared/de-de/main-navigation",{"_path":457,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"title":458,"button":459,"config":464,"_id":466,"_type":30,"_source":32,"_file":467,"_stem":468,"_extension":35},"/shared/de-de/banner","GitLab Duo Agent Platform ist jetzt in öffentlicher Beta!",{"text":460,"config":461},"Beta testen",{"href":462,"dataGaName":463,"dataGaLocation":44},"/de-de/gitlab-duo/agent-platform/","duo banner",{"layout":465},"release","content:shared:de-de:banner.yml","shared/de-de/banner.yml","shared/de-de/banner",{"_path":470,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":471,"_id":675,"_type":30,"title":676,"_source":32,"_file":677,"_stem":678,"_extension":35},"/shared/de-de/main-footer",{"text":472,"source":473,"edit":479,"contribute":484,"config":489,"items":494,"minimal":667},"Git ist eine Marke von Software Freedom Conservancy und unsere Verwendung von „GitLab“ erfolgt unter Lizenz.",{"text":474,"config":475},"Quelltext der Seite anzeigen",{"href":476,"dataGaName":477,"dataGaLocation":478},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":480,"config":481},"Diese Seite bearbeiten",{"href":482,"dataGaName":483,"dataGaLocation":478},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":485,"config":486},"Beteilige dich",{"href":487,"dataGaName":488,"dataGaLocation":478},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":490,"facebook":491,"youtube":492,"linkedin":493},"https://x.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[495,518,573,603,637],{"title":62,"links":496,"subMenu":501},[497],{"text":498,"config":499},"DevSecOps-Plattform",{"href":71,"dataGaName":500,"dataGaLocation":478},"devsecops platform",[502],{"title":205,"links":503},[504,508,513],{"text":505,"config":506},"Tarife anzeigen",{"href":207,"dataGaName":507,"dataGaLocation":478},"view plans",{"text":509,"config":510},"Vorteile von Premium",{"href":511,"dataGaName":512,"dataGaLocation":478},"/de-de/pricing/premium/","why premium",{"text":514,"config":515},"Vorteile von Ultimate",{"href":516,"dataGaName":517,"dataGaLocation":478},"/de-de/pricing/ultimate/","why ultimate",{"title":519,"links":520},"Lösungen",[521,526,529,531,536,541,545,548,551,556,558,560,563,568],{"text":522,"config":523},"Digitale Transformation",{"href":524,"dataGaName":525,"dataGaLocation":478},"/de-de/topics/digital-transformation/","digital transformation",{"text":527,"config":528},"Sicherheit und Compliance",{"href":153,"dataGaName":154,"dataGaLocation":478},{"text":138,"config":530},{"href":121,"dataGaName":122,"dataGaLocation":478},{"text":532,"config":533},"Agile Entwicklung",{"href":534,"dataGaName":535,"dataGaLocation":478},"/de-de/solutions/agile-delivery/","agile delivery",{"text":537,"config":538},"Cloud-Transformation",{"href":539,"dataGaName":540,"dataGaLocation":478},"/de-de/topics/cloud-native/","cloud transformation",{"text":542,"config":543},"SCM",{"href":135,"dataGaName":544,"dataGaLocation":478},"source code management",{"text":125,"config":546},{"href":127,"dataGaName":547,"dataGaLocation":478},"continuous integration & delivery",{"text":177,"config":549},{"href":179,"dataGaName":550,"dataGaLocation":478},"value stream management",{"text":552,"config":553},"GitOps",{"href":554,"dataGaName":555,"dataGaLocation":478},"/de-de/solutions/gitops/","gitops",{"text":190,"config":557},{"href":192,"dataGaName":193,"dataGaLocation":478},{"text":195,"config":559},{"href":197,"dataGaName":198,"dataGaLocation":478},{"text":561,"config":562},"Öffentlicher Sektor",{"href":202,"dataGaName":203,"dataGaLocation":478},{"text":564,"config":565},"Bildungswesen",{"href":566,"dataGaName":567,"dataGaLocation":478},"/de-de/solutions/education/","education",{"text":569,"config":570},"Finanzdienstleistungen",{"href":571,"dataGaName":572,"dataGaLocation":478},"/de-de/solutions/finance/","financial services",{"title":210,"links":574},[575,577,579,581,584,586,589,591,593,595,597,599,601],{"text":222,"config":576},{"href":224,"dataGaName":225,"dataGaLocation":478},{"text":227,"config":578},{"href":229,"dataGaName":230,"dataGaLocation":478},{"text":232,"config":580},{"href":234,"dataGaName":235,"dataGaLocation":478},{"text":237,"config":582},{"href":239,"dataGaName":583,"dataGaLocation":478},"docs",{"text":260,"config":585},{"href":262,"dataGaName":5,"dataGaLocation":478},{"text":255,"config":587},{"href":588,"dataGaName":258,"dataGaLocation":478},"/customers/",{"text":264,"config":590},{"href":266,"dataGaName":267,"dataGaLocation":478},{"text":277,"config":592},{"href":279,"dataGaName":280,"dataGaLocation":478},{"text":269,"config":594},{"href":271,"dataGaName":272,"dataGaLocation":478},{"text":282,"config":596},{"href":284,"dataGaName":285,"dataGaLocation":478},{"text":287,"config":598},{"href":289,"dataGaName":290,"dataGaLocation":478},{"text":292,"config":600},{"href":294,"dataGaName":295,"dataGaLocation":478},{"text":297,"config":602},{"href":299,"dataGaName":300,"dataGaLocation":478},{"title":315,"links":604},[605,607,609,611,613,615,617,621,626,628,630,632],{"text":322,"config":606},{"href":324,"dataGaName":317,"dataGaLocation":478},{"text":327,"config":608},{"href":329,"dataGaName":330,"dataGaLocation":478},{"text":335,"config":610},{"href":337,"dataGaName":338,"dataGaLocation":478},{"text":340,"config":612},{"href":342,"dataGaName":343,"dataGaLocation":478},{"text":345,"config":614},{"href":347,"dataGaName":348,"dataGaLocation":478},{"text":350,"config":616},{"href":352,"dataGaName":353,"dataGaLocation":478},{"text":618,"config":619},"Sustainability",{"href":620,"dataGaName":618,"dataGaLocation":478},"/sustainability/",{"text":622,"config":623},"Vielfalt, Inklusion und Zugehörigkeit",{"href":624,"dataGaName":625,"dataGaLocation":478},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":355,"config":627},{"href":357,"dataGaName":358,"dataGaLocation":478},{"text":365,"config":629},{"href":367,"dataGaName":368,"dataGaLocation":478},{"text":370,"config":631},{"href":372,"dataGaName":373,"dataGaLocation":478},{"text":633,"config":634},"Transparenzerklärung zu moderner Sklaverei",{"href":635,"dataGaName":636,"dataGaLocation":478},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":638,"links":639},"Nimm Kontakt auf",[640,643,645,647,652,657,662],{"text":641,"config":642},"Sprich mit einem Experten/einer Expertin",{"href":53,"dataGaName":54,"dataGaLocation":478},{"text":384,"config":644},{"href":386,"dataGaName":387,"dataGaLocation":478},{"text":389,"config":646},{"href":391,"dataGaName":392,"dataGaLocation":478},{"text":648,"config":649},"Status",{"href":650,"dataGaName":651,"dataGaLocation":478},"https://status.gitlab.com/","status",{"text":653,"config":654},"Nutzungsbedingungen",{"href":655,"dataGaName":656,"dataGaLocation":478},"/terms/","terms of use",{"text":658,"config":659},"Datenschutzerklärung",{"href":660,"dataGaName":661,"dataGaLocation":478},"/de-de/privacy/","privacy statement",{"text":663,"config":664},"Cookie-Einstellungen",{"dataGaName":665,"dataGaLocation":478,"id":666,"isOneTrustButton":107},"cookie preferences","ot-sdk-btn",{"items":668},[669,671,673],{"text":653,"config":670},{"href":655,"dataGaName":656,"dataGaLocation":478},{"text":658,"config":672},{"href":660,"dataGaName":661,"dataGaLocation":478},{"text":663,"config":674},{"dataGaName":665,"dataGaLocation":478,"id":666,"isOneTrustButton":107},"content:shared:de-de:main-footer.yml","Main Footer","shared/de-de/main-footer.yml","shared/de-de/main-footer",[680],{"_path":681,"_dir":682,"_draft":6,"_partial":6,"_locale":7,"content":683,"config":687,"_id":689,"_type":30,"title":18,"_source":32,"_file":690,"_stem":691,"_extension":35},"/en-us/blog/authors/itzik-gan-baruch","authors",{"name":18,"config":684},{"headshot":685,"ctfId":686},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749658921/Blog/Author%20Headshots/iganbaruch-headshot.jpg","iganbaruch",{"template":688},"BlogAuthor","content:en-us:blog:authors:itzik-gan-baruch.yml","en-us/blog/authors/itzik-gan-baruch.yml","en-us/blog/authors/itzik-gan-baruch",{"_path":693,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"header":694,"eyebrow":695,"blurb":696,"button":697,"secondaryButton":701,"_id":703,"_type":30,"title":704,"_source":32,"_file":705,"_stem":706,"_extension":35},"/shared/de-de/next-steps","Stelle jetzt bessere Software schneller bereit","Mehr als 50 % der Fortune-100-Unternehmen vertrauen GitLab","Erlebe, was dein Team mit der intelligenten\n\n\nDevSecOps-Plattform erreichen kann.\n",{"text":46,"config":698},{"href":699,"dataGaName":49,"dataGaLocation":700},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":51,"config":702},{"href":53,"dataGaName":54,"dataGaLocation":700},"content:shared:de-de:next-steps.yml","Next Steps","shared/de-de/next-steps.yml","shared/de-de/next-steps",1758326194177]