{"id":25665,"date":"2023-08-25T11:26:25","date_gmt":"2023-08-25T09:26:25","guid":{"rendered":"https:\/\/staging.digatus.com\/part-2-advanced-ci-cd-with-azure-devops\/"},"modified":"2025-11-27T11:40:52","modified_gmt":"2025-11-27T10:40:52","slug":"part-2-advanced-ci-cd-with-azure-devops","status":"publish","type":"post","link":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-azure-devops\/","title":{"rendered":"Part 2: Advanced CI\/CD with Azure DevOps"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"25665\" class=\"elementor elementor-25665 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>Part 2: Go Libraries, Pipeline Templates, and Versioning<\/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>After creating a simple pipeline in Part 1 of this article series, we dive deeper into the subject in Part 2. We create a library for our Go example project that will contain shared code with other future Go microservices. We face the challenge of keeping its Git repository private in Azure DevOps. Then we create a new pipeline for a Python application. To avoid duplicate code in the pipeline scripts, we create a pipeline template from which both pipelines inherit their basic structure. We also extend the pipelines with automatic versioning using Git tags, which will significantly simplify dependency management and the use of published Docker images.     <\/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>Incorporating Custom Go Libraries from Azure Repos<\/h5><p>Dependency management in Go is relatively simple: it only requires the URL to a Git repository and a Git tag. Go then checks out the commit with the corresponding tag from the Git repository and makes the code available during compilation. For public Git repositories, such as those on GitHub, not much can go wrong. For private Git repositories, however, a few extra steps are needed.   <\/p><p>First, we create a second Go project called <strong>example-go-library<\/strong> with a function that we want to use later in the <strong>example-go-project<\/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-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-25268\" 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-25267\" 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>For our library to be referenced later in other Go projects, it is essential to use the full URL as the module name:<\/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-25269\" 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>Otherwise, we will get error messages of the following type:<\/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-25270\" 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>The import in the <strong>example-go-project<\/strong> then looks like this:<\/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-25271\" 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>If the library is a private Git repo, as in this case, the following settings are also necessary (both in the local development environment and later in the Dockerfile):<\/p><ul><li>The environment variable <em>GOPRIVATE<\/em>. It prevents the library from being loaded via a public Go proxy (which has no access to the private Git repository). <\/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-25272\" 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>The following Git setting for authentication (a PAT can be created in Azure DevOps under the menu item &#8220;Personal Access Tokens&#8221; in the user menu in the top right corner):<\/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-25273\" 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>We take the small HTTP server from Part 1 of this article series as a basis and replace the import &#8220;github.com\/sirupsen\/logrus&#8221; with &#8220;dev.azure.com\/dennishellerdigatus\/CICD-Test\/_git\/example-go-library.git\/log&#8221; and all calls to logrus.Info with 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-25274\" 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>The Dockerfile must also be adjusted accordingly so that we have access to the private Git repository there. So we also set the environment variable GOPRIVATE and the Git setting with the PAT here: <\/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-25275\" 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>We also need to adjust the pipeline. Here too, we make the necessary preparations before the go mod download step. Fortunately, we don&#8217;t have to publish our personal PAT in the Dockerfile, but instead get an automatically generated PAT, as the build is already executed within the protected framework of our Azure DevOps project. We get this via the variable $(System.AccessToken) and it is only valid for the duration of the build. The complete pipeline now looks like this:    <\/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-25276\" 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>When executing the pipeline, we see that the PAT is used and masked by Azure DevOps:<\/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-25277\" 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>A test in a local shell then confirms that everything still works as before:<\/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-25278\" 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>Even though everything looks the same from the outside, we now have the advantage that we can move any code into the library and reuse it in other Go projects. Especially in a microservice landscape with many small services written in Go, there is usually a common code base, so introducing a library can save a lot of duplicate code. <\/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>The Second CI Pipeline \u2013 Python and Docker<\/h5><p>To bring some variety to our microservice landscape, we are now changing the language and creating another microservice in Python. This one is intended to call the REST endpoint of our Go microservice. Of course, the new microservice also gets a pipeline. Since Python, unlike Go, is interpreted at runtime, the build step is omitted here. The test steps look similar to those in the Go pipeline, and the Docker steps are identical. Later, we will extract the commonalities of both pipelines into a pipeline template to avoid duplicate code here as well and to be flexible for future additional pipelines.     <\/p><p>Here&#8217;s the simple code of our Python application that simply calls our Go microservice every 3 seconds and logs the result:<\/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-25279\" 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>For the sake of completeness, we&#8217;ll create a small unit test that mocks the Go microservice and captures the standard output with capsys:<\/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-25280\" 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>We then package the application into a Docker image. The environment variable <span style=\"color: #800080;\"><em>PYTHONUNBUFFERED<\/em><\/span>=<span style=\"color: #0000ff;\">1<\/span> is important to ensure that we can see the log outputs in real-time. We install the dependencies &#8211; in this case only one library, otherwise we would use a requirements file &#8211; with <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-25281\" 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>We create the pipeline analogous to the Go pipeline. As the first step, we again tell Azure DevOps which language and version we want to work with &#8211; in this case, Python 3.11.3. Next, we install the dependencies and then run the tests with <strong>pytest<\/strong>. The parameter <strong>&#8211;capture=tee-sys<\/strong> ensures that we can capture the standard output in the test. Using <strong>&#8211;cov=main<\/strong>, we calculate the code coverage, and with <strong>&#8211;junit-xml=report.xml<\/strong>, we generate the classic test report. Here too, there&#8217;s already a tool for processing the code coverage: the Python package <strong>coverage<\/strong>. Without further parameters, it&#8217;s compatible with the result format of <strong>pytest <\/strong>by default. The remaining steps for publishing the test results and for building and pushing the Docker image are identical to the 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-25282\" 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>Our first Python pipeline is ready. The result is impressive: <\/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-25283\" 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>As well as the test results and 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-25285\" 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-25284\" 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>Thinking Ahead: Pipeline Templates<\/h5><p>When we now compare our two pipelines &#8211; Go and Python &#8211; we notice that we have some identical and some different steps. To save work on future pipelines, Azure DevOps offers us the possibility to create pipeline templates. Also, if we want to change or extend a common part of the pipeline later, we only have to do this once in the common template and not in every single pipeline.  <\/p><p><span style=\"font-style: inherit; font-weight: inherit; color: var( --e-global-color-text ); background-color: var(--ast-global-color-4);\">The template hierarchy could even be continued further, so that we would have, for example, a common template for the entire company, then a sub-template for the project, and further sub-templates for CI and CD, different languages and frameworks, up to the final pipeline for a microservice. The keyword for using templates is, as in object-oriented programming,   <\/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);\">:. It&#8217;s important to note: a pipeline can only inherit from exactly one template. The key to making templates extensible are parameters, which can be used to fill in the placeholders in the template. These parameters can be simple text values, numbers, lists, complex objects, and even lists of complete pipeline steps. Default values are also possible. The parameters of a template are declared at the very top of the template under the section       <\/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);\">: and can then be used in the code of the template with the following notation: <\/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);\">. The template hierarchy and the parameters are evaluated when compiling the pipeline to create a single large pipeline script in which the parameters are already replaced. In contrast to the parameters, there are so-called variables that can be created, modified, and read at runtime. These are used with the following notation and are only interpreted at runtime:     <\/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 files are stored as YAML files, just like normal pipelines. Since they are used in several other Git repositories, it makes sense to create a separate Git repository for them, in our case we call it    <\/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>Back to our two pipelines: the basic structure (publishing the test results and building and uploading the Docker image) is identical. Only the middle part, building and testing, differs. Here&#8217;s an overview of all steps in both 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>It is therefore advisable to move the <span style=\"color: #0000ff;\">checkout<\/span> step and the last 4 steps into a common template and insert a placeholder with a parameter for the middle part. This looks as follows: <\/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-25286\" 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>If a parameter is noted as a single YAML list entry but contains a list, Azure DevOps automatically expands this without us having to write an extra <strong>each<\/strong> loop here. The template essentially looks like a normal pipeline and could also be used as such. If we were to create a pipeline in Azure DevOps with this template file, we would have to fill in the parameters manually when starting the pipeline, which is not possible for the <strong>stepList<\/strong> type. Therefore, the default value would be taken here: an empty list.   <\/p><p>We now modify our two existing pipelines so that they inherit from this template and set the values for the parameters. To do this, we first need to specify the Git repository that contains the template and give it an alias. After that, we can specify the template with <span style=\"color: #0000ff;\">extends<\/span>: and <span style=\"color: #0000ff;\">template<\/span>:. The syntax here is <strong>&lt;relative path&gt;@&lt;repository-alias&gt;<\/strong>. When a pipeline contains <span style=\"color: #0000ff;\">extends<\/span>: at the top level, it must not contain its own <span style=\"color: #0000ff;\">stages<\/span>:, <span style=\"color: #0000ff;\">jobs<\/span>:, or <span style=\"color: #0000ff;\">steps<\/span>: alongside it; instead, the entire pipeline must be built on the basic structure of the template, and all individual changes must be implemented via parameters. As mentioned before, Azure DevOps assembles a single large pipeline script from the template hierarchy before executing the pipeline, so we end up seeing exactly the same result.     <\/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-25287\" 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>Versioning with Git Tags<\/h5><p>Currently, we are using the Git commit hash as the Docker image tag, which is difficult to remember. A hard-coded tag like <strong>latest<\/strong> would have the disadvantage that we could only use one version in parallel. It therefore makes sense to introduce a versioning concept based on Semantic Versioning and integrate it into the pipeline so that the version number is automatically incremented and simultaneously used as the Docker image tag. We also create a Git tag for each build to be able to associate the Docker images with the source code later. Since the logic for this becomes relatively complex, we put it in a Bash script. Most likely, we will need it in future CI pipelines as well, so we immediately create another template <strong>azure-pipelines-ci.yaml<\/strong>, which serves as a new base template for <strong>azure-pipelines-ci-docker.yaml<\/strong>. This way, we already have a template hierarchy with three levels.      <\/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-25288\" 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>To explain the script &#8211; we distinguish different cases:<\/p><ul><li>If there is already a version tag directly on the commit for which the pipeline is running, we take this and don&#8217;t change anything about the version.<\/li><li>If the pipeline was started from a pull request, we don&#8217;t care about versioning. We just want to find out if the code and Docker image can be built and if the tests are successful. So we simply take the last previous version that we can find in the Git history and don&#8217;t change anything about the version.  <\/li><li>Otherwise, we search in the Git history for the nearest version tag in the past. If we are on a merge commit, we search in both directions and take the higher version. <\/li><li>If we don&#8217;t find any previous version, we start with version 0.1.<\/li><li>Otherwise, we increase the version as follows:<ul><li>On the <strong>master<\/strong> branch, we increase the minor version by 1.<\/li><li>On the <strong>dev<\/strong> branch, we increase the patch level by 1.<\/li><li>On feature branches, we don&#8217;t increase the version number.<\/li><\/ul><\/li><li>We also append a suffix to the version number:<ul><li>On the <strong>dev<\/strong> branch <strong>-dev<\/strong>.<\/li><li>On feature branches, a stripped-down version of the branch name.<\/li><li>For Go projects, it&#8217;s important that the tags are not moved, as the Go client caches the entire Git repository locally and stores a signature for each version that must not change anymore. For this use case, there is the parameter uniqueGitTags. If this is set to true, we create a separate unique version for each commit by appending another suffix that contains the commit hash and a timestamp.  <\/li><\/ul><\/li><\/ul><p>From the Bash script, we create a runtime pipeline variable called <span style=\"color: #339966;\">Version<\/span>. This is possible with the help of a so-called <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 Command<\/a>. To do this, we only need to write a special command to the standard output of the Bash script: <span style=\"color: #0000ff;\">echo<\/span> <span style=\"color: #339966;\">&#8220;##vso[task .setvariable variable=&#8221;&lt;name&gt;;isreadonly=true&#8221;]&lt;VALUE&gt;&#8221;<\/span>. This way, the version can be used in subsequent pipeline steps, for example as a Docker image tag. We only push the version tag back to the remote Git repository if the pipeline has run successfully; otherwise, it should be ignored. To do this, we force Azure DevOps to completely clean checkout the Git repository every time a pipeline is executed by setting the parameter <span style=\"color: #0000ff;\"><strong>clean<\/strong><\/span><strong>: true<\/strong> in the <span style=\"color: #0000ff;\">checkout<\/span>: step. We also need to set the parameter <span style=\"color: #0000ff;\"><strong>persistCredentials<\/strong><\/span><strong>: true<\/strong>, otherwise the credentials for the remote Git repository would be deleted for security reasons after the <span style=\"color: #0000ff;\">checkout<\/span>: step, and we would have no credentials to push the Git tag back.      <\/p><p>The <strong>azure-pipeline-ci-docker.yaml<\/strong> is then reduced to the two Docker steps. For referencing the template, the filename <strong>azure-pipeline-ci.yaml<\/strong> is sufficient here, as both files are in the same Git repository. It&#8217;s important to note the change of the Docker image tag from <span style=\"color: #339966;\">&#8216;$(Build.SourceVersion)&#8217;<\/span> to <span style=\"color: #339966;\">&#8216;$(Version)&#8217;<\/span>, to use the version number as the Docker image tag. If we are on the <strong>master<\/strong> branch, we set &#8211; as is common with Docker images &#8211; the <strong>latest<\/strong> tag in addition to the version number. We also add a <strong><span style=\"color: #0000ff;\">condition<\/span>:<\/strong> to the &#8220;Push Docker Image&#8221;<strong>&#8211;<\/strong>Step that skips the step in the context of a pull request. As with versioning, in the context of a pull request, we are only interested in checking the validity of the code and not publishing anything.     <\/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-25289\" 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>Now we start the pipeline for the <strong>example-python-project<\/strong>. At first, not much is visible from the major restructuring behind the scenes. New are the build steps <strong>Versioning<\/strong> and <strong>Create git tag.<\/strong> Since we don&#8217;t have any other version tag yet, we get the following message: Updating from &#8220;&#8221; to &#8220;0.0.1&#8221;.  <\/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-25290\" 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>For the Docker push, the version number is now used as the tag as desired:<\/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-25291\" 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>Unfortunately, pushing the Git tag still fails:<\/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-25292\" 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>This is because pipelines in Azure DevOps are executed in the name of a virtual user called <strong>&lt;Project-Name&gt; Build Service (&lt;Organization-Name&gt;)<\/strong>. For security reasons, this user by default does not have write permissions on the Git repositories. In our case, however, this is desired. To grant the necessary permission, we navigate through the menu via the gear icon in the bottom left to &#8220;Project Settings&#8221; \u2192 &#8220;Repositories&#8221; \u2192 &#8220;Security&#8221; tab \u2192 &#8220;Users&#8221; \u2192 &#8220;CICD-Test Build Service (dennishellerdigatus)&#8221; and change the value for <strong>Contribute<\/strong> in the table on the right from <strong>Not Set<\/strong> to <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-25293\" 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>Clicking on <strong>Rerun failed jobs<\/strong> in the failed pipeline shows us that we have found the right setting in the permissions jungle of Azure DevOps. The pipeline now runs successfully: <\/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-25294\" 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>We also see the new tags in the Git log and in Docker Hub:<\/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-25295\" 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-25296\" 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>Conclusion<\/h5><p>Azure DevOps offers a variety of options for creating both simple and complex pipelines. It&#8217;s nice that &#8211; unlike other CI\/CD systems &#8211; you can quickly and easily create pipelines without having to think about many issues. This is because the default values and settings are very well balanced between the necessary freedom and security. The more complex features are encapsulated in such a way that they don&#8217;t interfere when you don&#8217;t need them. Later, you can break out of these frameworks piece by piece, which means you have to write more code yourself and change settings, but you also have more features available. This way, complex scenarios can also be implemented with template hierarchies and Bash scripts.     <\/p><p>The reusability and extensibility of pipeline scripts through the template function &#8211; especially the insertion of entire step lists &#8211; is definitely one of the great strengths of Azure DevOps. And if the standard tasks are not sufficient, there is always the option to switch to the more comprehensive Bash level. All necessary tools are also installed there, such as git, go, and python. If we use a self-hosted build agent, we could install any additional tools like jq, make, or kustomize. Fortunately, we have hardly had to worry about permissions so far. There are also many configuration options here, but unfortunately, the effect of permissions is sometimes very difficult to understand. A plus point here, however, is that Azure DevOps offers a &#8216;Quick-Fix&#8217; button for frequently occurring permission problems, which automatically adjusts the permissions on the spot without having to navigate through complex menus.      <\/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>The idea for this article series arose from a situation with a client where we introduced CI\/CD because the manual workload was no longer manageable. The following instructions are therefore fresh from practice. For simplicity, we have shortened the long process of trial and error and present only the final result here. The code snippets are exemplary but sufficient to demonstrate the functionality.   <\/p>\n","protected":false},"author":2,"featured_media":25170,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[122],"tags":[138,132],"class_list":["post-25665","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-article","tag-cloud-en","tag-software-development"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Part 2: Advanced CI\/CD with Azure DevOps - digatus<\/title>\n<meta name=\"description\" content=\"Part 2: Go Libraries, Pipeline Templates, and Versioning. A Practical Guide for Your Own Development with 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\/en\/part-2-advanced-ci-cd-with-azure-devops\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Part 2: Advanced CI\/CD with Azure DevOps\" \/>\n<meta property=\"og:description\" content=\"Part 2: Go Libraries, Pipeline Templates, and Versioning. A Practical Guide.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-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:52+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/de.digatus.com\/wp-content\/uploads\/2023\/08\/CICD-Azure-DevOps_Teil2-1024x535.png\" \/>\n<meta name=\"author\" content=\"Annabell Renner\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Part 2: Advanced CI\/CD with Azure DevOps\" \/>\n<meta name=\"twitter:description\" content=\"Part 2: Go Libraries, Pipeline Templates, and Versioning. A Practical Guide.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/de.digatus.com\/wp-content\/uploads\/2023\/08\/CICD-Azure-DevOps_Teil2-1024x535.png\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Annabell Renner\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/part-2-advanced-ci-cd-with-azure-devops\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/part-2-advanced-ci-cd-with-azure-devops\\\/\"},\"author\":{\"name\":\"Annabell Renner\",\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/#\\\/schema\\\/person\\\/4902929f286856c9caf9575e10acd69e\"},\"headline\":\"Part 2: Advanced CI\\\/CD with Azure DevOps\",\"datePublished\":\"2023-08-25T09:26:25+00:00\",\"dateModified\":\"2025-11-27T10:40:52+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/part-2-advanced-ci-cd-with-azure-devops\\\/\"},\"wordCount\":2751,\"publisher\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/part-2-advanced-ci-cd-with-azure-devops\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/digatus.com\\\/wp-content\\\/uploads\\\/2022\\\/07\\\/CI_CD_DevOps_Azure.png\",\"keywords\":[\"Cloud\",\"Software Development\"],\"articleSection\":[\"Article\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/part-2-advanced-ci-cd-with-azure-devops\\\/\",\"url\":\"https:\\\/\\\/digatus.com\\\/en\\\/part-2-advanced-ci-cd-with-azure-devops\\\/\",\"name\":\"Part 2: Advanced CI\\\/CD with Azure DevOps - digatus\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/part-2-advanced-ci-cd-with-azure-devops\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/part-2-advanced-ci-cd-with-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:52+00:00\",\"description\":\"Part 2: Go Libraries, Pipeline Templates, and Versioning. A Practical Guide for Your Own Development with Azure DevOps.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/part-2-advanced-ci-cd-with-azure-devops\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/digatus.com\\\/en\\\/part-2-advanced-ci-cd-with-azure-devops\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/part-2-advanced-ci-cd-with-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},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/part-2-advanced-ci-cd-with-azure-devops\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\\\/\\\/digatus.com\\\/en\\\/home\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Part 2: Advanced CI\\\/CD with Azure DevOps\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/digatus.com\\\/en\\\/\",\"name\":\"digatus\",\"description\":\"Transforming IT, Empowering Business.\",\"publisher\":{\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/digatus.com\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/#organization\",\"name\":\"digatus\",\"url\":\"https:\\\/\\\/digatus.com\\\/en\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/#\\\/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\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/digatus.com\\\/en\\\/#\\\/schema\\\/person\\\/4902929f286856c9caf9575e10acd69e\",\"name\":\"Annabell Renner\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@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\\\/en\\\/author\\\/annabell\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Part 2: Advanced CI\/CD with Azure DevOps - digatus","description":"Part 2: Go Libraries, Pipeline Templates, and Versioning. A Practical Guide for Your Own Development with 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\/en\/part-2-advanced-ci-cd-with-azure-devops\/","og_locale":"en_US","og_type":"article","og_title":"Part 2: Advanced CI\/CD with Azure DevOps","og_description":"Part 2: Go Libraries, Pipeline Templates, and Versioning. A Practical Guide.","og_url":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-azure-devops\/","og_site_name":"digatus","article_published_time":"2023-08-25T09:26:25+00:00","article_modified_time":"2025-11-27T10:40:52+00:00","og_image":[{"url":"https:\/\/de.digatus.com\/wp-content\/uploads\/2023\/08\/CICD-Azure-DevOps_Teil2-1024x535.png","type":"","width":"","height":""}],"author":"Annabell Renner","twitter_card":"summary_large_image","twitter_title":"Part 2: Advanced CI\/CD with Azure DevOps","twitter_description":"Part 2: Go Libraries, Pipeline Templates, and Versioning. A Practical Guide.","twitter_image":"https:\/\/de.digatus.com\/wp-content\/uploads\/2023\/08\/CICD-Azure-DevOps_Teil2-1024x535.png","twitter_misc":{"Written by":"Annabell Renner","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-azure-devops\/#article","isPartOf":{"@id":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-azure-devops\/"},"author":{"name":"Annabell Renner","@id":"https:\/\/digatus.com\/en\/#\/schema\/person\/4902929f286856c9caf9575e10acd69e"},"headline":"Part 2: Advanced CI\/CD with Azure DevOps","datePublished":"2023-08-25T09:26:25+00:00","dateModified":"2025-11-27T10:40:52+00:00","mainEntityOfPage":{"@id":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-azure-devops\/"},"wordCount":2751,"publisher":{"@id":"https:\/\/digatus.com\/en\/#organization"},"image":{"@id":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-azure-devops\/#primaryimage"},"thumbnailUrl":"https:\/\/digatus.com\/wp-content\/uploads\/2022\/07\/CI_CD_DevOps_Azure.png","keywords":["Cloud","Software Development"],"articleSection":["Article"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-azure-devops\/","url":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-azure-devops\/","name":"Part 2: Advanced CI\/CD with Azure DevOps - digatus","isPartOf":{"@id":"https:\/\/digatus.com\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-azure-devops\/#primaryimage"},"image":{"@id":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-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:52+00:00","description":"Part 2: Go Libraries, Pipeline Templates, and Versioning. A Practical Guide for Your Own Development with Azure DevOps.","breadcrumb":{"@id":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-azure-devops\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-azure-devops\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-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},{"@type":"BreadcrumbList","@id":"https:\/\/digatus.com\/en\/part-2-advanced-ci-cd-with-azure-devops\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/digatus.com\/en\/home\/"},{"@type":"ListItem","position":2,"name":"Part 2: Advanced CI\/CD with Azure DevOps"}]},{"@type":"WebSite","@id":"https:\/\/digatus.com\/en\/#website","url":"https:\/\/digatus.com\/en\/","name":"digatus","description":"Transforming IT, Empowering Business.","publisher":{"@id":"https:\/\/digatus.com\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/digatus.com\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/digatus.com\/en\/#organization","name":"digatus","url":"https:\/\/digatus.com\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/digatus.com\/en\/#\/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\/en\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/digatus.com\/en\/#\/schema\/person\/4902929f286856c9caf9575e10acd69e","name":"Annabell Renner","image":{"@type":"ImageObject","inLanguage":"en-US","@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\/en\/author\/annabell\/"}]}},"_links":{"self":[{"href":"https:\/\/digatus.com\/en\/wp-json\/wp\/v2\/posts\/25665","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/digatus.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/digatus.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/digatus.com\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/digatus.com\/en\/wp-json\/wp\/v2\/comments?post=25665"}],"version-history":[{"count":1,"href":"https:\/\/digatus.com\/en\/wp-json\/wp\/v2\/posts\/25665\/revisions"}],"predecessor-version":[{"id":28943,"href":"https:\/\/digatus.com\/en\/wp-json\/wp\/v2\/posts\/25665\/revisions\/28943"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/digatus.com\/en\/wp-json\/wp\/v2\/media\/25170"}],"wp:attachment":[{"href":"https:\/\/digatus.com\/en\/wp-json\/wp\/v2\/media?parent=25665"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/digatus.com\/en\/wp-json\/wp\/v2\/categories?post=25665"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/digatus.com\/en\/wp-json\/wp\/v2\/tags?post=25665"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}