{"id":15405,"date":"2023-08-25T11:26:25","date_gmt":"2023-08-25T09:26:25","guid":{"rendered":"https:\/\/digatus.com\/?p=15405"},"modified":"2025-11-27T11:40:41","modified_gmt":"2025-11-27T10:40:41","slug":"teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops","status":"publish","type":"post","link":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/","title":{"rendered":"Teil 2: CI\/CD f\u00fcr Fortgeschrittene mit Azure DevOps"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"15405\" class=\"elementor elementor-15405\" data-elementor-post-type=\"post\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-a014c68 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"a014c68\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-d36618b\" data-id=\"d36618b\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-59dfede elementor-widget elementor-widget-text-editor\" data-id=\"59dfede\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h5>Teil 2: Go Bibliotheken, Pipeline Templates und Versionierung<\/h5>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-f53c9b9 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"f53c9b9\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-ef99a8e\" data-id=\"ef99a8e\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-c35c145 elementor-widget elementor-widget-text-editor\" data-id=\"c35c145\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p><em>Nachdem wir in Teil 1 dieser Artikelserie bereits eine einfach Pipeline erstellt haben, tauchen wir in Teil 2 etwas tiefer in die Materie ein. Wir erstellen f\u00fcr unser Go-Beispiel-Projekt eine Bibliothek, die gemeinsamen Code mit anderen zuk\u00fcnftigen Go-Microservices enthalten wird. Dabei haben wir die Herausforderung, dass dessen Git-Repository in Azure DevOps privat bleiben soll. Danach erstellen wir eine neue Pipeline f\u00fcr eine Python-Anwendung. Um doppelten Code in den Pipeline-Skripten zu vermeiden, erstellen wir ein Pipeline-Template, von dem beide Pipelines ihre Grundstruktur erben. Au\u00dferdem erweitern wir die Pipelines um eine automatische Versionierung mit Git Tags, was die Abh\u00e4ngigkeitsverwaltung und die Verwendung der publizierten Docker-Images deutlich vereinfachen wird.<\/em><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-dfb5090 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"dfb5090\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-ec0952d\" data-id=\"ec0952d\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-413196e elementor-widget elementor-widget-text-editor\" data-id=\"413196e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h5>Einbinden eigener Go-Bibliotheken aus Azure Repos<\/h5><p>Die Abh\u00e4ngigkeitsverwaltung in Go ist relativ simpel: es ben\u00f6tigt nur die URL zu einem Git-Repository und einen Git Tag. Go checkt dann aus dem Git-Repository den Commit mit dem entsprechenden Tag aus und stellt den Code beim Kompilieren zur Verf\u00fcgung. F\u00fcr \u00f6ffentliche Git-Repositories, zum Beispiel auf GitHub, kann nicht viel schiefgehen. F\u00fcr private Git-Repositories dagegen braucht es ein paar extra Handgriffe.<\/p><p>Zuerst erstellen wir ein zweites Go-Projekt namens <strong>example-go-library<\/strong> mit einer Funktion, die wir sp\u00e4ter im <strong>example-go-project <\/strong>verwenden wollen.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-7d6d2df elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"7d6d2df\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-b529bed\" data-id=\"b529bed\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-3bf8f60 elementor-widget elementor-widget-image\" data-id=\"3bf8f60\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"768\" height=\"165\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-library_go.mod_-768x165.png\" class=\"attachment-medium_large size-medium_large wp-image-15409\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-library_go.mod_-768x165.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-library_go.mod_-300x65.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-library_go.mod_.png 868w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e979bf1 elementor-widget elementor-widget-image\" data-id=\"e979bf1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"768\" height=\"167\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-library_log_message.go_-768x167.png\" class=\"attachment-medium_large size-medium_large wp-image-15407\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-library_log_message.go_-768x167.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-library_log_message.go_-300x65.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-library_log_message.go_.png 871w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-26c1dcc elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"26c1dcc\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-a6bf6af\" data-id=\"a6bf6af\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-43521e8 elementor-widget elementor-widget-text-editor\" data-id=\"43521e8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Damit unsere Bibliothek sp\u00e4ter in anderen Go Projekten referenziert werden kann, ist es zwingend notwendig, die volle URL als Modul-Namen zu verwenden:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-4c2cc61 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"4c2cc61\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-613b5d6\" data-id=\"613b5d6\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-e6c547a elementor-widget elementor-widget-image\" data-id=\"e6c547a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"768\" height=\"30\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/module-768x30.png\" class=\"attachment-medium_large size-medium_large wp-image-15412\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/module-768x30.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/module-300x12.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/module.png 890w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c0a9211 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c0a9211\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-67516c6\" data-id=\"67516c6\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-4c5f82a elementor-widget elementor-widget-text-editor\" data-id=\"4c5f82a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Ansonsten bekommen wir Fehlermeldungen folgender Art:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-7889591 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"7889591\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-8821294\" data-id=\"8821294\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-21b43ed elementor-widget elementor-widget-image\" data-id=\"21b43ed\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"126\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/go.mod-error-768x126.png\" class=\"attachment-medium_large size-medium_large wp-image-15414\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/go.mod-error-768x126.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/go.mod-error-300x49.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/go.mod-error.png 889w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-a28546a elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"a28546a\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-23eea8a\" data-id=\"23eea8a\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-a4d99c0 elementor-widget elementor-widget-text-editor\" data-id=\"a4d99c0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Der Import im <strong>example-go-project<\/strong> sieht dann wie folgt aus:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-495160b elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"495160b\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-80d8f69\" data-id=\"80d8f69\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-38f9930 elementor-widget elementor-widget-image\" data-id=\"38f9930\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"144\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_go.mod_-768x144.png\" class=\"attachment-medium_large size-medium_large wp-image-15422\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_go.mod_-768x144.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_go.mod_-300x56.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_go.mod_.png 869w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-11b0511 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"11b0511\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-3d27b3e\" data-id=\"3d27b3e\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-d58c368 elementor-widget elementor-widget-text-editor\" data-id=\"d58c368\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Falls die Bibliothek wie in diesem Fall ein privates Git-Repo ist, sind au\u00dferdem folgende Einstellungen n\u00f6tig (sowohl in der lokalen Entwicklungsumgebung als auch sp\u00e4ter im Dockerfile):<\/p><ul><li>Die Umgebungsvariable <em>GOPRIVATE<\/em>. Sie verhindert, dass die Library \u00fcber einen \u00f6ffentlichen Go-Proxy geladen wird (der ja keinen Zugriff auf das private Git-Repository hat).<\/li><\/ul>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-9a7dae9 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"9a7dae9\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f8c068b\" data-id=\"f8c068b\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-9ef7a3e elementor-widget elementor-widget-image\" data-id=\"9ef7a3e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"30\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/GOPRIVATE-768x30.png\" class=\"attachment-medium_large size-medium_large wp-image-15424\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/GOPRIVATE-768x30.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/GOPRIVATE-300x12.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/GOPRIVATE.png 803w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-8b88cc6 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"8b88cc6\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-2e56b4f\" data-id=\"2e56b4f\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2619d5b elementor-widget elementor-widget-text-editor\" data-id=\"2619d5b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<ul><li>Das folgende Git-Setting f\u00fcr die Authentifizierung (ein PAT kann in Azure DevOps unter dem Men\u00fc-Punkt \u201ePersonal Access Tokens\u201c im Benutzer-Men\u00fc oben rechts erstellt werden):<\/li><\/ul>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-11f664f elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"11f664f\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-c7861f5\" data-id=\"c7861f5\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-ad5ca5b elementor-widget elementor-widget-image\" data-id=\"ad5ca5b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"50\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/gitconfig-768x50.png\" class=\"attachment-medium_large size-medium_large wp-image-15426\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/gitconfig-768x50.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/gitconfig-300x19.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/gitconfig.png 801w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-7f74973 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"7f74973\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-b6bfce3\" data-id=\"b6bfce3\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-b9e2c83 elementor-widget elementor-widget-text-editor\" data-id=\"b9e2c83\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Wir nehmen als Grundlage den kleinen HTTP-Server aus Teil 1 dieser Artikel-Serie und ersetzen den Import &#8222;github.com\/sirupsen\/logrus&#8220; durch &#8222;dev.azure.com\/dennishellerdigatus\/CICD-Test\/_git\/example-go-library.git\/log&#8220; und alle Aufrufe von logrus.Info durch log.Message.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-58ccbbb elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"58ccbbb\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-76126f6\" data-id=\"76126f6\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-55869c6 elementor-widget elementor-widget-image\" data-id=\"55869c6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"463\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_main.go_-768x463.png\" class=\"attachment-medium_large size-medium_large wp-image-15428\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_main.go_-768x463.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_main.go_-300x181.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_main.go_.png 870w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-b79b3b8 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"b79b3b8\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-ce07633\" data-id=\"ce07633\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-cfdcef5 elementor-widget elementor-widget-text-editor\" data-id=\"cfdcef5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Das Dockerfile muss auch entsprechend angepasst werden, damit wir dort Zugriff auf das private Git-Repository haben. Wir setzen also auch hier die Umgebungsvariable GOPRIVATE und das Git-Setting mit dem PAT:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-8471cc0 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"8471cc0\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-9e9bb34\" data-id=\"9e9bb34\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-149142e elementor-widget elementor-widget-image\" data-id=\"149142e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"420\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_Dockerfile-768x420.png\" class=\"attachment-medium_large size-medium_large wp-image-15430\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_Dockerfile-768x420.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_Dockerfile-300x164.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_Dockerfile.png 870w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-feec094 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"feec094\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-38f1e8f\" data-id=\"38f1e8f\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-c6f846c elementor-widget elementor-widget-text-editor\" data-id=\"c6f846c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Die Pipeline m\u00fcssen wir ebenfalls anpassen. Auch dort treffen wir vor dem go mod download-Step die n\u00f6tigen Vorbereitungen. Erfreulicherweise m\u00fcssen wir hier nicht unseren pers\u00f6nlichen PAT im Dockerfile ver\u00f6ffentlichen, sondern bekommen einen automatisch generierten PAT, da der Build ja bereits im gesch\u00fctzten Rahmen unseres Azure-DevOps-Projekts ausgef\u00fchrt wird. Diesen bekommen wir \u00fcber die Variable $(System.AccessToken) und er ist nur f\u00fcr die Dauer des Builds g\u00fcltig. Die komplette Pipeline sieht nun wie folgt aus:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-5b212fd elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"5b212fd\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-7d651fc\" data-id=\"7d651fc\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-5328517 elementor-widget elementor-widget-image\" data-id=\"5328517\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"1947\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_azure-pipelines.yaml_-768x1947.png\" class=\"attachment-medium_large size-medium_large wp-image-15434\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_azure-pipelines.yaml_-768x1947.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_azure-pipelines.yaml_-118x300.png 118w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_azure-pipelines.yaml_-404x1024.png 404w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_azure-pipelines.yaml_-606x1536.png 606w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_azure-pipelines.yaml_-808x2048.png 808w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-go-project_azure-pipelines.yaml_.png 850w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-ca578ad elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"ca578ad\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-8c921be\" data-id=\"8c921be\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-b1e1914 elementor-widget elementor-widget-text-editor\" data-id=\"b1e1914\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Beim Ausf\u00fchren der Pipeline sehen wir, dass der PAT eingesetzt und von Azure DevOps maskiert wird:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-791bb4a elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"791bb4a\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0210835\" data-id=\"0210835\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-ed92285 elementor-widget elementor-widget-image\" data-id=\"ed92285\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"1394\" height=\"847\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-04-27-213738.png\" class=\"attachment-full size-full wp-image-15436\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-04-27-213738.png 1394w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-04-27-213738-300x182.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-04-27-213738-1024x622.png 1024w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-04-27-213738-768x467.png 768w\" sizes=\"(max-width: 1394px) 100vw, 1394px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-8c0c31e elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"8c0c31e\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-8759023\" data-id=\"8759023\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-04e24be elementor-widget elementor-widget-text-editor\" data-id=\"04e24be\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Danach best\u00e4tigt uns ein Test in einer lokalen Shell, dass immer noch alles wie bisher funktioniert:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-fb8c6a4 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"fb8c6a4\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-e723c65\" data-id=\"e723c65\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-7c2e1e1 elementor-widget elementor-widget-image\" data-id=\"7c2e1e1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"67\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-04-26-122318-768x67.png\" class=\"attachment-medium_large size-medium_large wp-image-15438\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-04-26-122318-768x67.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-04-26-122318-300x26.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-04-26-122318-1024x90.png 1024w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-04-26-122318.png 1176w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-43b57b6 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"43b57b6\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-bc4a2bd\" data-id=\"bc4a2bd\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-9797d9d elementor-widget elementor-widget-text-editor\" data-id=\"9797d9d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Auch wenn nach au\u00dfen alles gleich aussieht, haben wir jetzt den Vorteil, dass wir beliebigen Code in die Bibliothek verschieben und in anderen Go-Projekten wiederverwenden k\u00f6nnen. Gerade in einer Microservice-Landschaft mit vielen kleinen, in Go geschriebenen Services, gibt es meistens eine gemeinsame Code-Basis, sodass man durch die Einf\u00fchrung einer Bibliothek viel Duplicate Code sparen kann.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-6eebefb elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"6eebefb\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-6fdfa8b\" data-id=\"6fdfa8b\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-f1be3db elementor-widget elementor-widget-text-editor\" data-id=\"f1be3db\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h5>Die zweite CI Pipeline \u2013 Python und Docker<\/h5><p>Um etwas Abwechslung in unsere Microservice-Landschaft zu bringen, wechseln wir nun dennoch die Sprache und erstellen einen weiteren Microservice in Python. Dieser soll den REST-Endpunkt unseres Go-Microservices aufrufen. Nat\u00fcrlich bekommt der neue Microservice auch eine Pipeline spendiert. Da Python in Gegensatz zu Go erst zur Laufzeit interpretiert wird, f\u00e4llt hier der Build-Step weg. Die Test-Steps sehen \u00e4hnlich aus wie in der Go-Pipeline und die Docker-Steps sind identisch. Sp\u00e4ter werden wir die Gemeinsamkeiten beider Pipelines in ein Pipeline-Template extrahieren, um auch hier Duplicate Code zu vermeiden und f\u00fcr zuk\u00fcnftige weitere Pipelines flexibel zu sein.<\/p><p>Hier der simple Code unserer Python-Anwendung, die einfach im 3-Sekunden-Takt unseren Go-Microservice aufruft und das Ergebnis loggt:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-fbcc75e elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"fbcc75e\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-5c3f0ee\" data-id=\"5c3f0ee\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-a5cebce elementor-widget elementor-widget-image\" data-id=\"a5cebce\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"422\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_main.py_-768x422.png\" class=\"attachment-medium_large size-medium_large wp-image-15440\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_main.py_-768x422.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_main.py_-300x165.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_main.py_.png 869w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-84ec043 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"84ec043\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-3e79aef\" data-id=\"3e79aef\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-067bb68 elementor-widget elementor-widget-text-editor\" data-id=\"067bb68\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Der Vollst\u00e4ndigkeit halber erstellen wir noch einen kleinen Unit-Test, der den Go-Microservice mockt und mit capsys die Standardausgabe abf\u00e4ngt:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-fc3a113 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"fc3a113\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-841e86b\" data-id=\"841e86b\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-7c585f0 elementor-widget elementor-widget-image\" data-id=\"7c585f0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"423\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_main_test.py_-768x423.png\" class=\"attachment-medium_large size-medium_large wp-image-15442\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_main_test.py_-768x423.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_main_test.py_-300x165.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_main_test.py_.png 869w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-126cd75 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"126cd75\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-beadcf5\" data-id=\"beadcf5\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-df077ff elementor-widget elementor-widget-text-editor\" data-id=\"df077ff\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Die Anwendung packen wir dann wieder in ein Docker Image. Die Umgebungsvariable <span style=\"color: #800080;\"><em>PYTHONUNBUFFERED<\/em><\/span>=<span style=\"color: #0000ff;\">1<\/span> ist wichtig um sicherzustellen, dass wir die Log-Ausgaben in Echtzeit sehen k\u00f6nnen. Die Abh\u00e4ngigkeiten \u2013 in diesem Fall nur eine Bibliothek, ansonsten w\u00fcrden wir eine requirements-Datei verwenden \u2013 installieren wir mit <span style=\"color: #0000ff;\">pip<\/span>.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c06edc7 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c06edc7\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-a1e904b\" data-id=\"a1e904b\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-1ee824b elementor-widget elementor-widget-image\" data-id=\"1ee824b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"297\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_Dockerfile-768x297.png\" class=\"attachment-medium_large size-medium_large wp-image-15446\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_Dockerfile-768x297.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_Dockerfile-300x116.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_Dockerfile.png 847w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-623ec50 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"623ec50\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-d4d688e\" data-id=\"d4d688e\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-0e6e0da elementor-widget elementor-widget-text-editor\" data-id=\"0e6e0da\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Die Pipeline erstellen wir analog zur Go-Pipeline. Als ersten Step teilen wir Azure DevOps wieder mit, mit welcher Sprache und welcher Version wir arbeiten wollen \u2013 in diesem Fall mit Python 3.11.3. Als n\u00e4chstes installieren wir die Abh\u00e4ngigkeiten und danach f\u00fchren wir die Tests mit <strong>pytest<\/strong> aus. Der Parameter <strong>&#8211;capture=tee-sys<\/strong> sorgt daf\u00fcr, dass wir im Test die Standardausgabe abfangen k\u00f6nnen. Mittels <strong>&#8211;cov=main<\/strong> lassen wir die Code Coverage berechnen und mit <strong>&#8211;junit-xml=report.xml<\/strong> erzeugen wir den klassischen Test-Bericht. Auch hier gibt es bereits ein Tool zum Aufbereiten der Code Coverage: das Python-Package <strong>coverage<\/strong>. Ohne weitere Parameter ist es standardm\u00e4\u00dfig mit dem Ergebnis-Format von <strong>pytest <\/strong>kompatibel. Die restlichen Steps zum Ver\u00f6ffentlichen der Test-Ergebnisse und zum Bauen und Pushen des Docker Images sind identisch mit der Go-Pipeline:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-5bfc617 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"5bfc617\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-24ff154\" data-id=\"24ff154\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2631911 elementor-widget elementor-widget-image\" data-id=\"2631911\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"1323\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_azure-pipelines.yaml_-768x1323.png\" class=\"attachment-medium_large size-medium_large wp-image-15448\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_azure-pipelines.yaml_-768x1323.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_azure-pipelines.yaml_-174x300.png 174w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_azure-pipelines.yaml_-594x1024.png 594w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_azure-pipelines.yaml_.png 869w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c636742 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c636742\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-ed15861\" data-id=\"ed15861\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-b1db171 elementor-widget elementor-widget-text-editor\" data-id=\"b1db171\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Fertig ist unsere erste Python-Pipeline. Das Ergebnis kann sich sehen lassen:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-f39d221 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"f39d221\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-7c6a463\" data-id=\"7c6a463\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-4561c7e elementor-widget elementor-widget-image\" data-id=\"4561c7e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"1390\" height=\"847\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-02-160536.png\" class=\"attachment-full size-full wp-image-15450\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-02-160536.png 1390w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-02-160536-300x183.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-02-160536-1024x624.png 1024w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-02-160536-768x468.png 768w\" sizes=\"(max-width: 1390px) 100vw, 1390px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-f15d925 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"f15d925\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-caa7956\" data-id=\"caa7956\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-3d7ed36 elementor-widget elementor-widget-text-editor\" data-id=\"3d7ed36\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Ebenso die Test Ergebnisse und die Coverage:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-2965c15 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"2965c15\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-86505ef\" data-id=\"86505ef\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-4906fa2 elementor-widget elementor-widget-image\" data-id=\"4906fa2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"1392\" height=\"844\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-03-055114.png\" class=\"attachment-full size-full wp-image-15454\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-03-055114.png 1392w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-03-055114-300x182.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-03-055114-1024x621.png 1024w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-03-055114-768x466.png 768w\" sizes=\"(max-width: 1392px) 100vw, 1392px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0e15433 elementor-widget elementor-widget-image\" data-id=\"0e15433\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"1394\" height=\"848\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-03-055206.png\" class=\"attachment-full size-full wp-image-15452\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-03-055206.png 1394w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-03-055206-300x182.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-03-055206-1024x623.png 1024w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-05-03-055206-768x467.png 768w\" sizes=\"(max-width: 1394px) 100vw, 1394px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-014c826 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"014c826\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f138d1a\" data-id=\"f138d1a\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-4e0cf9d elementor-widget elementor-widget-text-editor\" data-id=\"4e0cf9d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h5>Vorrausschauend denken: Pipeline-Templates<\/h5><p>Wenn wir nun unsere beiden Pipelines \u2013 Go und Python \u2013 miteinander vergleichen, stellen wir fest, dass wir einige identische und einige unterschiedliche Steps haben. Um bei zuk\u00fcnftigen Pipelines Arbeit zu sparen, bietet uns Azure DevOps die M\u00f6glichkeit an, Pipeline-Templates zu erstellen. Auch, falls wir sp\u00e4ter einen gemeinsamen Teil der Pipeline \u00e4ndern oder erweitern wollen, m\u00fcssen wir dies dann nur einmal im gemeinsamen Template tun und nicht in jeder einzelnen Pipeline.<\/p><p><span style=\"font-style: inherit; font-weight: inherit; color: var( --e-global-color-text ); background-color: var(--ast-global-color-4);\">Die Template-Hierarchie lie\u00dfe sich sogar weiter fortf\u00fchren, sodass wir z.B. ein gemeinsames Template f\u00fcr das gesamte Unternehmen h\u00e4tten, dann ein Unter-Template f\u00fcr das Projekt und weitere Unter-Templates f\u00fcr CI und CD, verschiedene Sprachen und Frameworks bis zur finalen Pipeline f\u00fcr einen Microservice. Das Schl\u00fcsselwort zum Verwenden von Templates lautet wie in der objekt-orientierten Programmierung <\/span><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: #0000ff;\">extends<\/span><span style=\"font-style: inherit; font-weight: inherit; color: var( --e-global-color-text ); background-color: var(--ast-global-color-4);\">:. Wichtig ist: eine Pipeline kann nur von genau einem Template erben. Der Schl\u00fcssel um Templates erweiterbar zu machen, sind Parameter, mit denen sich die Platzhalter im Template f\u00fcllen lassen. Diese Parameter k\u00f6nnen einfache Textwerte, Zahlen, Listen, komplexe Objekte und sogar Listen von kompletten Pipeline-Steps sein. Default-Werte sind ebenso m\u00f6glich. Die Parameter eines Template werden ganz oben im Template unter dem Abschnitt <\/span><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-4); color: #0000ff;\">parameters<\/span><span style=\"font-style: inherit; font-weight: inherit; color: var( --e-global-color-text ); background-color: var(--ast-global-color-4);\">: deklariert und k\u00f6nnen dann im Code des Templates mit der folgenden Notation verwendet werden: <\/span><strong style=\"font-style: inherit; color: var( --e-global-color-text ); background-color: var(--ast-global-color-4);\">{{ parameters.xxx }}<\/strong><span style=\"font-style: inherit; font-weight: inherit; color: var( --e-global-color-text ); background-color: var(--ast-global-color-4);\">. Die Template-Hierarchie und die Parameter werden beim Kompilieren der Pipeline ausgewertet, um ein einziges gro\u00dfes Pipeline-Skript zu erstellen, in dem die Parameter bereits ersetzt sind. Im Gegensatz zu den Parametern gibt es sogenannte Variablen, die zur Laufzeit erstellt, ver\u00e4ndert und ausgelesen werden k\u00f6nnen. Diese werden mit der folgenden Notation verwendet und erst zur Laufzeit interpretiert: <\/span><strong style=\"font-style: inherit; color: var( --e-global-color-text ); background-color: var(--ast-global-color-4);\">$(variable)<\/strong><span style=\"font-style: inherit; font-weight: inherit; color: var( --e-global-color-text ); background-color: var(--ast-global-color-4);\">. Template-Dateien werden wie normale Pipelines als YAML-Dateien gespeichert. Da sie in mehreren anderen Git-Repositories verwendet werden, bietet es sich an, ein eigenes Git-Repository f\u00fcr sie zu erstellen, in unserem Fall nennen wir es <\/span><strong style=\"font-style: inherit; color: var( --e-global-color-text ); background-color: var(--ast-global-color-4);\">example-pipeline-templates<\/strong><span style=\"font-style: inherit; font-weight: inherit; color: var( --e-global-color-text ); background-color: var(--ast-global-color-4);\">.<\/span><\/p><p>Zur\u00fcck zu unseren beiden Pipelines: die Grundstruktur (das Ver\u00f6ffentlichen der Test-Ergebnisse und das Bauen und Hochladen des Docker Images) ist identisch. Nur der mittlere Teil, das Bauen und Testen unterscheidet sich. Hier eine \u00dcbersicht \u00fcber alle Steps der beiden Pipelines:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-4dcf604 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"4dcf604\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f1c2725\" data-id=\"f1c2725\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-56c2919 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"56c2919\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-9fe9502\" data-id=\"9fe9502\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-a6602ed elementor-widget elementor-widget-text-editor\" data-id=\"a6602ed\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Es bietet sich also an, den <span style=\"color: #0000ff;\">checkout<\/span>: Step und die letzten 4 Steps in ein gemeinsames Template zu verschieben und f\u00fcr den mittleren Teil einen Platzhalter mit Parameter einzusetzen. Das sieht wie folgt aus:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-b3ca769 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"b3ca769\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-ca8aa39\" data-id=\"ca8aa39\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-92bd39d elementor-widget elementor-widget-image\" data-id=\"92bd39d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"928\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci-docker.yaml_-768x928.png\" class=\"attachment-medium_large size-medium_large wp-image-15467\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci-docker.yaml_-768x928.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci-docker.yaml_-248x300.png 248w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci-docker.yaml_-847x1024.png 847w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci-docker.yaml_.png 852w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-03afaae elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"03afaae\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0aa5d39\" data-id=\"0aa5d39\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-4d62a68 elementor-widget elementor-widget-text-editor\" data-id=\"4d62a68\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Falls ein Parameter als einzelner YAML-Listen-Eintrag notiert wird, aber eine Liste enth\u00e4lt, expandiert Azure DevOps diese automatisch, ohne dass wir hier extra eine <strong>each<\/strong>-Schleife schreiben m\u00fcssen. Das Template sieht im Prinzip aus wie eine normale Pipeline und k\u00f6nnte auch als solche verwendet werden. Wenn wir in Azure DevOps eine Pipeline mit dieser Template-Datei anlegen w\u00fcrden, m\u00fcssten wir beim Starten der Pipeline die Parameter von Hand f\u00fcllen, was f\u00fcr den Typ <strong>stepList<\/strong> nicht m\u00f6glich ist. Deshalb w\u00fcrde hier der Default-Wert genommen werden: eine leere Liste.<\/p><p>Wir \u00e4ndern nun unsere beiden bisherigen Pipelines, sodass sie von diesem Template erben und setzen dabei die Werte f\u00fcr die Parameter. Dazu m\u00fcssen wir zuerst das Git-Repository angeben, das das Template enth\u00e4lt und es mit einem Alias benennen. Danach k\u00f6nnen wir mit <span style=\"color: #0000ff;\">extends<\/span>: und <span style=\"color: #0000ff;\">template<\/span>: das Template angeben. Die Syntax lautet hier <strong>&lt;relativer Pfad&gt;@&lt;repository-Alias&gt;<\/strong>. Wenn eine Pipeline <span style=\"color: #0000ff;\">extends<\/span>: auf oberster Ebene enth\u00e4lt, darf sie nicht daneben noch eigene <span style=\"color: #0000ff;\">stages<\/span>:, <span style=\"color: #0000ff;\">jobs<\/span>: oder <span style=\"color: #0000ff;\">steps<\/span>: enthalten, sondern die komplette Pipeline muss \u00fcber das Grundger\u00fcst des Templates gebaut sein und alle individuellen \u00c4nderungen m\u00fcssen \u00fcber Parameter realisiert werden. Wie bereits erw\u00e4hnt, bastelt Azure DevOps vor dem Ausf\u00fchren der Pipeline aus der Template-Hierarchie ein einziges gro\u00dfes Pipeline-Skript zusammen, sodass wir am Ende exakt das gleiche Ergebnis zu sehen bekommen.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-affb830 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"affb830\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-63136df\" data-id=\"63136df\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-0fb7638 elementor-widget elementor-widget-image\" data-id=\"0fb7638\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"806\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_azure-pipelines.yaml_new-768x806.png\" class=\"attachment-medium_large size-medium_large wp-image-15471\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_azure-pipelines.yaml_new-768x806.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_azure-pipelines.yaml_new-286x300.png 286w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-python-project_azure-pipelines.yaml_new.png 774w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-3d5ec72 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"3d5ec72\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-8ae6323\" data-id=\"8ae6323\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-c3da5ae elementor-widget elementor-widget-text-editor\" data-id=\"c3da5ae\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h5>Versionierung mit Git Tags<\/h5><p>Momentan verwenden wir den Git Commit-Hash als Docker Image Tag, welcher schwer zu merken ist. Ein hart-codierter Tag wie <strong>latest<\/strong> h\u00e4tte den Nachteil, dass wir immer nur eine Version parallel verwenden k\u00f6nnten. Es macht also Sinn, ein Versionierungs-Konzept auf Basis von Semantic Versioning einzuf\u00fchren und dieses in die Pipeline zu integrieren, sodass die Versionsnummer automatisch hochgez\u00e4hlt und gleichzeitig als Docker Image Tag verwendet wird. Au\u00dferdem erstellen wir bei jedem Build ein Git Tag, um sp\u00e4ter die Docker Images dem Source-Code zuordnen zu k\u00f6nnen. Da die Logik hierf\u00fcr relativ komplex wird, packen wir sie in ein Bash-Skript. H\u00f6chstwahrscheinlich werden wir sie in zuk\u00fcnftigen CI-Pipelines ebenfalls brauchen, deshalb erstellen wir gleich ein weiteres Template <strong>azure-pipelines-ci.yaml<\/strong>, das als neues Basis-Template f\u00fcr <strong>azure-pipelines-ci-docker.yaml<\/strong> dient. Somit haben wir schon eine Template-Hierarchie mit drei Ebenen.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-25f2662 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"25f2662\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-76e16dd\" data-id=\"76e16dd\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-3d1ae2d elementor-widget elementor-widget-image\" data-id=\"3d1ae2d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"1749\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci.yaml_-768x1749.png\" class=\"attachment-medium_large size-medium_large wp-image-15473\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci.yaml_-768x1749.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci.yaml_-132x300.png 132w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci.yaml_-450x1024.png 450w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci.yaml_-674x1536.png 674w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci.yaml_-899x2048.png 899w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci.yaml_.png 1339w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-37a61e3 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"37a61e3\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-60797ec\" data-id=\"60797ec\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-e14d2f6 elementor-widget elementor-widget-text-editor\" data-id=\"e14d2f6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Zur Erkl\u00e4rung des Skriptes &#8211; wir unterscheiden verschiedene F\u00e4lle:<\/p><ul><li>Wenn direkt auf dem Commit, f\u00fcr den die Pipeline l\u00e4uft, schon ein Versions-Tag ist, nehmen wir diesen und \u00e4ndern nichts an der Version.<\/li><li>Wurde die Pipeline aus einem Pull Request heraus gestartet, ist uns die Versionierung egal. Wir wollen nur herausfinden, ob der Code und das Docker Image gebaut werden k\u00f6nnen und ob die Tests erfolgreich sind. Also nehmen wir einfach die letzte bisherige Version, die wir in der Git-Historie finden k\u00f6nnen und \u00e4ndern nichts an der Version.<\/li><li>Ansonsten suchen wir in der Git-Historie in der Vergangenheit den am n\u00e4chsten liegenden Versions-Tag. Falls wir auf einem Merge-Commit sind, suchen wir in beide Richtungen und nehmen die h\u00f6here Version.<\/li><li>Falls wir keine bisherige Version finden, starten wir mit der Version 0.1.<\/li><li>Ansonsten erh\u00f6hen wir die Version wie folgt:<ul><li>Auf dem <strong>master<\/strong>-Branch erh\u00f6hen wir die Minor Version um 1.<\/li><li>Auf dem <strong>dev<\/strong>-Branch erh\u00f6hen wir den Patch-Level um 1.<\/li><li>Auf Feature-Branches erh\u00f6hen wir die Versionsnummer nicht.<\/li><\/ul><\/li><li>Au\u00dferdem h\u00e4ngen wir ein Suffix an die Versionsnummer:<ul><li>Auf dem <strong>dev<\/strong>-Branch <strong>-dev<\/strong>.<\/li><li>Auf Feature-Branches eine abgespeckte Variante des Branch-Namens.<\/li><li>Bei Go-Projekten ist es wichtig, dass die Tags nicht verschoben werden, da der Go-Client das komplette Git-Repository lokal cacht und zu jeder Version eine Signatur speichert, die sich nicht mehr \u00e4ndern darf. F\u00fcr diesen Anwendungsfall gibt es den Parameter uniqueGitTags. Wenn dieser auf true gesetzt ist, erstellen wir f\u00fcr jeden Commit eine eigene eindeutige Version, indem wir einen weiteren Suffix anh\u00e4ngen, der den Commit-Hash und einen Zeitstempel enth\u00e4lt.<\/li><\/ul><\/li><\/ul><p>Aus dem Bash-Skript heraus erstellen wir eine Laufzeit-Pipeline-Variable namens <span style=\"color: #339966;\">Version<\/span>. Das ist m\u00f6glich mit Hilfe eines sogenannten <a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/devops\/pipelines\/scripts\/logging-commands?view=azure-devops&amp;tabs=bash#setvariable-initialize-or-modify-the-value-of-a-variable\">Logging-Commands<\/a>. Dazu m\u00fcssen wir nur einen speziellen Befehl in die Standard-Ausgabe des Bash-Skriptes schreiben: <span style=\"color: #0000ff;\">echo<\/span> <span style=\"color: #339966;\">&#8222;##vso[task.setvariable variable=&lt;NAME&gt;;isreadonly=true]&lt;WERT&gt;&#8220;<\/span>. \u00a0So kann die Version in den darauffolgenden Pipeline-Steps verwendet werden, zum Beispiel als Docker Image Tag. Nur wenn die Pipeline erfolgreich durchgelaufen ist, pushen wir den Versions-Tag zur\u00fcck ins Remote-Git-Repository, ansonsten soll er ignoriert werden. Dazu zwingen wir Azure DevOps bei jeder Ausf\u00fchrung einer Pipeline das Git-Repository komplett clean auschecken, indem wir im <span style=\"color: #0000ff;\">checkout<\/span>: -Step den Parameter <span style=\"color: #0000ff;\"><strong>clean<\/strong><\/span><strong>: true<\/strong> setzen. Au\u00dferdem m\u00fcssen wir noch den Parameter <span style=\"color: #0000ff;\"><strong>persistCredentials<\/strong><\/span><strong>: true<\/strong> setzen, ansonsten w\u00fcrden nach dem <span style=\"color: #0000ff;\">checkout<\/span>: -Step die Zugangsdaten f\u00fcrs Remote-Git-Repository aus Sicherheitsgr\u00fcnden gel\u00f6scht werden und wir h\u00e4tten keine Zugangsdaten um den Git-Tag zur\u00fcck zu pushen.<\/p><p>Die <strong>azure-pipeline-ci-docker.yaml<\/strong> verk\u00fcrzt sich dann auf die beiden Docker-Steps. F\u00fcr die Referenzierung des Templates reicht hier der Dateiname <strong>azure-pipeline-ci.yaml<\/strong> aus, da sich beide Dateien im selben Git-Repository befinden. Wichtig ist hier jetzt nat\u00fcrlich noch die \u00c4nderung des Docker Image Tags von <span style=\"color: #339966;\">&#8218;$(Build.SourceVersion)&#8216;<\/span> zu <span style=\"color: #339966;\">&#8218;$(Version)&#8216;<\/span>., um die Versionsnummer als Docker Image Tag zu verwenden. Falls wir auf dem <strong>master<\/strong>-Branch sind, setzen wir \u2013 wie bei Docker Images \u00fcblich \u2013 neben der Versionsnummer noch den <strong>latest<\/strong>-Tag. Au\u00dferdem f\u00fcgen wir beim \u201ePush Docker Image\u201c<strong>&#8211;<\/strong>Step eine <strong><span style=\"color: #0000ff;\">condition<\/span>:<\/strong> hinzu, die den Step im Kontext eines Pull Requests \u00fcberspringen l\u00e4sst. Ebenso wie bei der Versionierung sind wir im Kontext eines Pull Requests n\u00e4mlich nur daran interessiert, die Validit\u00e4t des Codes zu pr\u00fcfen und nicht irgendetwas zu ver\u00f6ffentlichen.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-a1539fb elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"a1539fb\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-981277a\" data-id=\"981277a\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-ff6c458 elementor-widget elementor-widget-image\" data-id=\"ff6c458\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"855\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci-docker.yaml_neu-768x855.png\" class=\"attachment-medium_large size-medium_large wp-image-15475\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci-docker.yaml_neu-768x855.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci-docker.yaml_neu-269x300.png 269w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/example-pipeline-templates_azure-pipelines-ci-docker.yaml_neu.png 848w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-6d7789d elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"6d7789d\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-caac58b\" data-id=\"caac58b\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-94bdca6 elementor-widget elementor-widget-text-editor\" data-id=\"94bdca6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Nun starten wir die Pipeline f\u00fcrs <strong>example-python-project<\/strong>. Von dem gro\u00dfen Umbau hinter den Kulissen ist erstmal nicht viel zu sehen. Neu sind die Build-Steps <strong>Versioning<\/strong> und <strong>Create git tag.<\/strong> Da wir bisher keinen anderen Versions-Tag haben, bekommen wir die folgende Meldung: Updating from &#8222;&#8220; to &#8222;0.0.1&#8220;.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-732ffa2 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"732ffa2\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-d601345\" data-id=\"d601345\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-7a0e23b elementor-widget elementor-widget-image\" data-id=\"7a0e23b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"2062\" height=\"1315\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122101.png\" class=\"attachment-full size-full wp-image-15477\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122101.png 2062w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122101-300x191.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122101-1024x653.png 1024w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122101-768x490.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122101-1536x980.png 1536w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122101-2048x1306.png 2048w\" sizes=\"(max-width: 2062px) 100vw, 2062px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c03f6b4 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c03f6b4\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-075aaa1\" data-id=\"075aaa1\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-1d92a3b elementor-widget elementor-widget-text-editor\" data-id=\"1d92a3b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Beim Docker Push wird jetzt wie gew\u00fcnscht die Versionsnummer als Tag verwendet:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c02b88e elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c02b88e\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-cb206bd\" data-id=\"cb206bd\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-af50bb4 elementor-widget elementor-widget-image\" data-id=\"af50bb4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"1287\" height=\"483\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122038.png\" class=\"attachment-full size-full wp-image-15479\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122038.png 1287w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122038-300x113.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122038-1024x384.png 1024w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122038-768x288.png 768w\" sizes=\"(max-width: 1287px) 100vw, 1287px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-1b0ce5e elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"1b0ce5e\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-7662ab4\" data-id=\"7662ab4\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-02678ad elementor-widget elementor-widget-text-editor\" data-id=\"02678ad\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Leider schl\u00e4gt das pushen des Git Tags noch fehl:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-ae82d55 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"ae82d55\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-e119261\" data-id=\"e119261\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-95b2adb elementor-widget elementor-widget-image\" data-id=\"95b2adb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"2421\" height=\"507\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122209.png\" class=\"attachment-full size-full wp-image-15481\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122209.png 2421w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122209-300x63.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122209-1024x214.png 1024w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122209-768x161.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122209-1536x322.png 1536w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-122209-2048x429.png 2048w\" sizes=\"(max-width: 2421px) 100vw, 2421px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-2b9aad0 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"2b9aad0\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-eadf85d\" data-id=\"eadf85d\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-d8d8683 elementor-widget elementor-widget-text-editor\" data-id=\"d8d8683\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Das liegt daran, dass Pipelines in Azure DevOps im Namen eines virtuellen Benutzers namens <strong>&lt;Projekt-Name&gt; Build Service (&lt;Organisations-Name&gt;)<\/strong> ausgef\u00fchrt werden. Dieser hat aus Sicherheitsgr\u00fcnden standardm\u00e4\u00dfig keine Schreibrechte auf den Git-Repositories. In unserem Fall ist das aber erw\u00fcnscht. Um die n\u00f6tige Berechtigung zu erteilen, hangeln wir uns \u00fcber das Zahnrad unten links durchs Men\u00fc zu \u201eProject Settings\u201c \u00e0 \u201eRepositories\u201c \u00e0 Reiter \u201eSecurity\u201c \u00e0 \u201eUsers\u201c \u00e0 \u201eCICD-Test Build Service (dennishellerdigatus)\u201c und \u00e4ndern in der Tabelle rechts den Wert bei <strong>Contribute<\/strong> von <strong>Not Set<\/strong> auf <strong>Allow<\/strong>:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-9b7c81e elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"9b7c81e\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-5c488f9\" data-id=\"5c488f9\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-ab51aad elementor-widget elementor-widget-image\" data-id=\"ab51aad\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"2141\" height=\"1315\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123045.png\" class=\"attachment-full size-full wp-image-15483\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123045.png 2141w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123045-300x184.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123045-1024x629.png 1024w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123045-768x472.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123045-1536x943.png 1536w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123045-2048x1258.png 2048w\" sizes=\"(max-width: 2141px) 100vw, 2141px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-95c6327 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"95c6327\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-e43af90\" data-id=\"e43af90\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-0e45daf elementor-widget elementor-widget-text-editor\" data-id=\"0e45daf\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Ein Klick auf <strong>Rerun failed jobs<\/strong> in der fehlgeschlagenen Pipeline zeigt uns, dass wir die richtige Einstellung im Berechtigungs-Dschungel von Azure DevOps erwischt haben. Die Pipeline l\u00e4uft jetzt erfolgreich durch:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c1abc40 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c1abc40\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-38c9b42\" data-id=\"38c9b42\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2a7cdda elementor-widget elementor-widget-image\" data-id=\"2a7cdda\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"2146\" height=\"1314\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123232.png\" class=\"attachment-full size-full wp-image-15485\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123232.png 2146w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123232-300x184.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123232-1024x627.png 1024w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123232-768x470.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123232-1536x940.png 1536w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123232-2048x1254.png 2048w\" sizes=\"(max-width: 2146px) 100vw, 2146px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-7bf789d elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"7bf789d\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-a949ddb\" data-id=\"a949ddb\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-7fb6475 elementor-widget elementor-widget-text-editor\" data-id=\"7fb6475\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Ebenfalls sehen wir im Git Log und im Docker Hub die neuen Tags:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-a2dd719 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"a2dd719\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-68b4661\" data-id=\"68b4661\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-d32d383 elementor-widget elementor-widget-image\" data-id=\"d32d383\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"2151\" height=\"1311\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123519.png\" class=\"attachment-full size-full wp-image-15487\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123519.png 2151w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123519-300x183.png 300w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123519-1024x624.png 1024w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123519-768x468.png 768w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123519-1536x936.png 1536w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-07-123519-2048x1248.png 2048w\" sizes=\"(max-width: 2151px) 100vw, 2151px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8017a66 elementor-widget elementor-widget-image\" data-id=\"8017a66\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"733\" height=\"559\" src=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-14-071238.png\" class=\"attachment-full size-full wp-image-15489\" alt=\"\" srcset=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-14-071238.png 733w, https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/Screenshot-2023-06-14-071238-300x229.png 300w\" sizes=\"(max-width: 733px) 100vw, 733px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-2dd417d elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"2dd417d\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-5759e33\" data-id=\"5759e33\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-5d35d04 elementor-widget elementor-widget-text-editor\" data-id=\"5d35d04\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h5>Fazit<\/h5><p>Azure DevOps bietet eine Vielzahl an M\u00f6glichkeiten, sowohl einfache als auch komplexe Pipelines zu erstellen. Sch\u00f6n ist, dass man \u2013 im Gegensatz zu anderen CI\/CD-Systemen \u2013 schnell und einfache Pipelines erstellen kann, ohne sich um viele Themen Gedanken machen zu m\u00fcssen. Das liegt daran, dass die Standard-Werte und -Einstellungen zwischen der n\u00f6tigen Freiheit und Sicherheit sehr gut ausbalanciert sind. Die komplexeren Features sind so verkapselt, dass sie nicht st\u00f6ren, wenn man sie nicht braucht. Sp\u00e4ter kann man St\u00fcck f\u00fcr St\u00fcck aus diesen Rahmen ausbrechen, wodurch man zwar mehr Code selber schreiben und Einstellungen \u00e4ndern muss, aber auch mehr Features zur Verf\u00fcgung hat. So lassen sich mit Template-Hierarchien und Bash-Skripten auch komplexe Szenarien umsetzen.<\/p><p>Die Wiederverwendbarkeit und Erweiterbarkeit von Pipeline-Skripten durch die Template-Funktion \u2013 vor allem das Einf\u00fcgen von ganzen Step-Listen \u2013 ist definitiv eine der gro\u00dfen St\u00e4rken von Azure DevOps. Und falls die Standard-Tasks nicht ausreichen, gibt es jederzeit die Option, auf die umfangreichere Bash-Ebene zu wechseln. Dort sind ebenfalls alle n\u00f6tigen Tools installiert, wie git, go und python. Falls wir einen selbst-gehosteten Build-Agent verwenden, k\u00f6nnten wir beliebige weitere Tools installieren wie zum Beispiel jq, make oder kustomize. Um Berechtigungen mussten wir uns bisher zum Gl\u00fcck fast gar nicht k\u00fcmmern. Hier gibt es auch sehr viele M\u00f6glichkeiten zur Konfiguration, nur leider ist die Wirkungsweise der Berechtigungen teilweise sehr schwer nachzuvollziehen. Ein Pluspunkt hier ist jedoch, dass Azure DevOps f\u00fcr h\u00e4ufig vorkommende Berechtigungsprobleme einen \u201eQuick-Fix\u201c-Button anbietet, der an Ort und Stelle automatisch die Berechtigungen anpasst, ohne dass man sich durch komplexe Men\u00fcs durchhangeln muss.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Die Idee f\u00fcr diese Artikelserie entstand aus der Situation bei einem Kunden, bei dem wir CI\/CD einf\u00fchrten, weil der manuelle Arbeitsaufwand nicht mehr zu bewerkstelligen war. Die nachfolgenden Anleitungen sind also frisch aus der Praxis entstanden. Der Einfachheit halber haben wir den langen Weg des Ausprobierens und der Fehlersuche gek\u00fcrzt und pr\u00e4sentieren hier nur das Endergebnis. Die Code-Ausschnitte sind beispielhaft, aber ausreichend, um die Funktionalit\u00e4t zu pr\u00e4sentieren.<\/p>\n","protected":false},"author":2,"featured_media":13322,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[95],"tags":[73,75],"class_list":["post-15405","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-artikel","tag-cloud","tag-softwareentwicklung"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Teil 2: CI\/CD f\u00fcr Fortgeschrittene mit Azure DevOps - digatus<\/title>\n<meta name=\"description\" content=\"Teil 2: Go Bibliotheken, Pipeline Templates und Versionierung. Eine Anleitung aus der Praxis f\u00fcr die eigene Entwicklung mit Azure DevOps.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Teil 2: CI\/CD f\u00fcr Fortgeschrittene mit Azure DevOps\" \/>\n<meta property=\"og:description\" content=\"Teil 2: Go Bibliotheken, Pipeline Templates und Versionierung. Eine Anleitung aus der Praxis.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/\" \/>\n<meta property=\"og:site_name\" content=\"digatus\" \/>\n<meta property=\"article:published_time\" content=\"2023-08-25T09:26:25+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-27T10:40:41+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/CICD-Azure-DevOps_Teil2.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"627\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Annabell Renner\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Teil 2: CI\/CD f\u00fcr Fortgeschrittene mit Azure DevOps\" \/>\n<meta name=\"twitter:description\" content=\"Teil 2: Go Bibliotheken, Pipeline Templates und Versionierung. Eine Anleitung aus der Praxis.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/CICD-Azure-DevOps_Teil2.png\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Annabell Renner\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"20\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\\\/\"},\"author\":{\"name\":\"Annabell Renner\",\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/#\\\/schema\\\/person\\\/4902929f286856c9caf9575e10acd69e\"},\"headline\":\"Teil 2: CI\\\/CD f\u00fcr Fortgeschrittene mit Azure DevOps\",\"datePublished\":\"2023-08-25T09:26:25+00:00\",\"dateModified\":\"2025-11-27T10:40:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\\\/\"},\"wordCount\":2705,\"publisher\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/digatus.com\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/CI_CD_DevOps_Azure.png\",\"keywords\":[\"Cloud\",\"Softwareentwicklung\"],\"articleSection\":[\"Artikel\"],\"inLanguage\":\"de\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\\\/\",\"url\":\"https:\\\/\\\/digatus.com\\\/de\\\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\\\/\",\"name\":\"Teil 2: CI\\\/CD f\u00fcr Fortgeschrittene mit Azure DevOps - digatus\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/digatus.com\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/CI_CD_DevOps_Azure.png\",\"datePublished\":\"2023-08-25T09:26:25+00:00\",\"dateModified\":\"2025-11-27T10:40:41+00:00\",\"description\":\"Teil 2: Go Bibliotheken, Pipeline Templates und Versionierung. Eine Anleitung aus der Praxis f\u00fcr die eigene Entwicklung mit Azure DevOps.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/digatus.com\\\/de\\\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\\\/#primaryimage\",\"url\":\"https:\\\/\\\/digatus.com\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/CI_CD_DevOps_Azure.png\",\"contentUrl\":\"https:\\\/\\\/digatus.com\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/CI_CD_DevOps_Azure.png\",\"width\":950,\"height\":633,\"caption\":\"ci_cd_devops_azure\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\\\/\\\/digatus.com\\\/de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Teil 2: CI\\\/CD f\u00fcr Fortgeschrittene mit Azure DevOps\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/#website\",\"url\":\"https:\\\/\\\/digatus.com\\\/de\\\/\",\"name\":\"digatus\",\"description\":\"Transforming IT, Empowering Business.\",\"publisher\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/digatus.com\\\/de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/#organization\",\"name\":\"digatus\",\"url\":\"https:\\\/\\\/digatus.com\\\/de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/digatus.com\\\/wp-content\\\/uploads\\\/2025\\\/01\\\/Logo_digatus_green_web_rgb.png\",\"contentUrl\":\"https:\\\/\\\/digatus.com\\\/wp-content\\\/uploads\\\/2025\\\/01\\\/Logo_digatus_green_web_rgb.png\",\"width\":1200,\"height\":312,\"caption\":\"digatus\"},\"image\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/digatus.com\\\/de\\\/#\\\/schema\\\/person\\\/4902929f286856c9caf9575e10acd69e\",\"name\":\"Annabell Renner\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f260d8c39a817b4f01ed758cefc9933458252cc43e8c4c292328cc6009d4fea2?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f260d8c39a817b4f01ed758cefc9933458252cc43e8c4c292328cc6009d4fea2?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f260d8c39a817b4f01ed758cefc9933458252cc43e8c4c292328cc6009d4fea2?s=96&d=mm&r=g\",\"caption\":\"Annabell Renner\"},\"url\":\"https:\\\/\\\/digatus.com\\\/de\\\/author\\\/annabell\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Teil 2: CI\/CD f\u00fcr Fortgeschrittene mit Azure DevOps - digatus","description":"Teil 2: Go Bibliotheken, Pipeline Templates und Versionierung. Eine Anleitung aus der Praxis f\u00fcr die eigene Entwicklung mit Azure DevOps.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/","og_locale":"de_DE","og_type":"article","og_title":"Teil 2: CI\/CD f\u00fcr Fortgeschrittene mit Azure DevOps","og_description":"Teil 2: Go Bibliotheken, Pipeline Templates und Versionierung. Eine Anleitung aus der Praxis.","og_url":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/","og_site_name":"digatus","article_published_time":"2023-08-25T09:26:25+00:00","article_modified_time":"2025-11-27T10:40:41+00:00","og_image":[{"width":1200,"height":627,"url":"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/CICD-Azure-DevOps_Teil2.png","type":"image\/png"}],"author":"Annabell Renner","twitter_card":"summary_large_image","twitter_title":"Teil 2: CI\/CD f\u00fcr Fortgeschrittene mit Azure DevOps","twitter_description":"Teil 2: Go Bibliotheken, Pipeline Templates und Versionierung. Eine Anleitung aus der Praxis.","twitter_image":"https:\/\/digatus.com\/wp-content\/uploads\/2023\/08\/CICD-Azure-DevOps_Teil2.png","twitter_misc":{"Verfasst von":"Annabell Renner","Gesch\u00e4tzte Lesezeit":"20\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/#article","isPartOf":{"@id":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/"},"author":{"name":"Annabell Renner","@id":"https:\/\/digatus.com\/de\/#\/schema\/person\/4902929f286856c9caf9575e10acd69e"},"headline":"Teil 2: CI\/CD f\u00fcr Fortgeschrittene mit Azure DevOps","datePublished":"2023-08-25T09:26:25+00:00","dateModified":"2025-11-27T10:40:41+00:00","mainEntityOfPage":{"@id":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/"},"wordCount":2705,"publisher":{"@id":"https:\/\/digatus.com\/de\/#organization"},"image":{"@id":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/#primaryimage"},"thumbnailUrl":"https:\/\/digatus.com\/wp-content\/uploads\/2022\/07\/CI_CD_DevOps_Azure.png","keywords":["Cloud","Softwareentwicklung"],"articleSection":["Artikel"],"inLanguage":"de"},{"@type":"WebPage","@id":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/","url":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/","name":"Teil 2: CI\/CD f\u00fcr Fortgeschrittene mit Azure DevOps - digatus","isPartOf":{"@id":"https:\/\/digatus.com\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/#primaryimage"},"image":{"@id":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/#primaryimage"},"thumbnailUrl":"https:\/\/digatus.com\/wp-content\/uploads\/2022\/07\/CI_CD_DevOps_Azure.png","datePublished":"2023-08-25T09:26:25+00:00","dateModified":"2025-11-27T10:40:41+00:00","description":"Teil 2: Go Bibliotheken, Pipeline Templates und Versionierung. Eine Anleitung aus der Praxis f\u00fcr die eigene Entwicklung mit Azure DevOps.","breadcrumb":{"@id":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/#primaryimage","url":"https:\/\/digatus.com\/wp-content\/uploads\/2022\/07\/CI_CD_DevOps_Azure.png","contentUrl":"https:\/\/digatus.com\/wp-content\/uploads\/2022\/07\/CI_CD_DevOps_Azure.png","width":950,"height":633,"caption":"ci_cd_devops_azure"},{"@type":"BreadcrumbList","@id":"https:\/\/digatus.com\/de\/teil-2-ci-cd-fuer-fortgeschrittene-mit-azure-devops\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/digatus.com\/de\/"},{"@type":"ListItem","position":2,"name":"Teil 2: CI\/CD f\u00fcr Fortgeschrittene mit Azure DevOps"}]},{"@type":"WebSite","@id":"https:\/\/digatus.com\/de\/#website","url":"https:\/\/digatus.com\/de\/","name":"digatus","description":"Transforming IT, Empowering Business.","publisher":{"@id":"https:\/\/digatus.com\/de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/digatus.com\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/digatus.com\/de\/#organization","name":"digatus","url":"https:\/\/digatus.com\/de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/digatus.com\/de\/#\/schema\/logo\/image\/","url":"https:\/\/digatus.com\/wp-content\/uploads\/2025\/01\/Logo_digatus_green_web_rgb.png","contentUrl":"https:\/\/digatus.com\/wp-content\/uploads\/2025\/01\/Logo_digatus_green_web_rgb.png","width":1200,"height":312,"caption":"digatus"},"image":{"@id":"https:\/\/digatus.com\/de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/digatus.com\/de\/#\/schema\/person\/4902929f286856c9caf9575e10acd69e","name":"Annabell Renner","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/f260d8c39a817b4f01ed758cefc9933458252cc43e8c4c292328cc6009d4fea2?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f260d8c39a817b4f01ed758cefc9933458252cc43e8c4c292328cc6009d4fea2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f260d8c39a817b4f01ed758cefc9933458252cc43e8c4c292328cc6009d4fea2?s=96&d=mm&r=g","caption":"Annabell Renner"},"url":"https:\/\/digatus.com\/de\/author\/annabell\/"}]}},"_links":{"self":[{"href":"https:\/\/digatus.com\/de\/wp-json\/wp\/v2\/posts\/15405","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/digatus.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/digatus.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/digatus.com\/de\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/digatus.com\/de\/wp-json\/wp\/v2\/comments?post=15405"}],"version-history":[{"count":1,"href":"https:\/\/digatus.com\/de\/wp-json\/wp\/v2\/posts\/15405\/revisions"}],"predecessor-version":[{"id":28942,"href":"https:\/\/digatus.com\/de\/wp-json\/wp\/v2\/posts\/15405\/revisions\/28942"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/digatus.com\/de\/wp-json\/wp\/v2\/media\/13322"}],"wp:attachment":[{"href":"https:\/\/digatus.com\/de\/wp-json\/wp\/v2\/media?parent=15405"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/digatus.com\/de\/wp-json\/wp\/v2\/categories?post=15405"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/digatus.com\/de\/wp-json\/wp\/v2\/tags?post=15405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}