{"id":47122,"date":"2024-09-24T04:49:21","date_gmt":"2024-09-24T04:49:21","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=47122"},"modified":"2024-09-24T09:47:19","modified_gmt":"2024-09-24T09:47:19","slug":"azure-devops-pipelines-fundamental-tutorials","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/azure-devops-pipelines-fundamental-tutorials\/","title":{"rendered":"Azure DevOps Pipelines Fundamental Tutorials"},"content":{"rendered":"\n<p>Here is an in-depth, step-by-step tutorial on <strong>Azure DevOps Pipelines<\/strong> that covers everything from the fundamentals to advanced concepts. This guide is designed to help you understand the basics of pipelines, how to set them up, and how to configure them for advanced use cases such as continuous integration (CI) and continuous deployment (CD).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>1. Introduction to Azure DevOps Pipelines<\/strong><\/h3>\n\n\n\n<p>Azure DevOps Pipelines allow you to automate builds, tests, and deployments in a repeatable and scalable manner. It integrates well with various development languages and platforms such as .NET, Java, Node.js, Python, and more.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Key Concepts of Pipelines<\/strong>:<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Pipelines<\/strong>: Automates building, testing, and deploying your applications.<\/li>\n\n\n\n<li><strong>Continuous Integration (CI)<\/strong>: Automates building and testing code whenever a developer commits changes.<\/li>\n\n\n\n<li><strong>Continuous Deployment (CD)<\/strong>: Automates deploying the code to production or other environments after successful builds and tests.<\/li>\n\n\n\n<li><strong>YAML Pipelines<\/strong>: The pipeline is defined in YAML, making it version-controllable and portable.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>2. Setting up Azure DevOps Pipelines (Fundamentals)<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Step 1: Creating a Project in Azure DevOps<\/strong><\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Sign in to your Azure DevOps organization or create a new organization.<\/li>\n\n\n\n<li>Click on <strong>New Project<\/strong>.<\/li>\n\n\n\n<li>Name your project, select visibility (Public or Private), and click <strong>Create<\/strong>.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Step 2: Setting Up a Pipeline<\/strong><\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Navigate to <strong>Pipelines<\/strong> \u2192 <strong>Create Pipeline<\/strong>.<\/li>\n\n\n\n<li>Select your repository where the code is stored (e.g., GitHub, Azure Repos, Bitbucket).<\/li>\n\n\n\n<li>Choose <strong>YAML<\/strong> or <strong>Classic Editor<\/strong> for pipeline creation:\n<ul class=\"wp-block-list\">\n<li><strong>YAML<\/strong>: Recommended for flexibility and version control.<\/li>\n\n\n\n<li><strong>Classic Editor<\/strong>: GUI-based setup, easier for beginners.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Step 3: Configuring a YAML Pipeline<\/strong><\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Azure DevOps will automatically detect your project type (e.g., .NET Core, Python, Node.js) and suggest a pipeline template.<\/li>\n\n\n\n<li>Customize your YAML file. Example for a .NET Core project:<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">trigger:\n  - main\n\n<span class=\"hljs-attr\">pool<\/span>:\n  vmImage: <span class=\"hljs-string\">'ubuntu-latest'<\/span>\n\n<span class=\"hljs-attr\">steps<\/span>:\n- task: UseDotNet@<span class=\"hljs-number\">2<\/span>\n  <span class=\"hljs-attr\">inputs<\/span>:\n    packageType: <span class=\"hljs-string\">'sdk'<\/span>\n    <span class=\"hljs-attr\">version<\/span>: <span class=\"hljs-string\">'6.x'<\/span>\n\n- script: dotnet build\n- script: dotnet test\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>3. Pipeline Architecture &amp; Components<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Triggers<\/strong>:<\/h4>\n\n\n\n<p>Triggers are used to specify when the pipeline should run. There are two primary types:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>CI Trigger<\/strong>: Automatically runs the pipeline when code is pushed or merged to a specific branch.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">trigger:\n  branches:\n    <span class=\"hljs-keyword\">include<\/span>:\n      - main\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>Scheduled Trigger<\/strong>: Runs the pipeline at specific times.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">schedules:\n  - cron: <span class=\"hljs-string\">\"0 0 * * *\"<\/span>\n    branches:\n      <span class=\"hljs-keyword\">include<\/span>:\n        - main\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Pools<\/strong>:<\/h4>\n\n\n\n<p>A pool defines the agent (machine) that will run your pipeline. Example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">pool:\n  vmImage: <span class=\"hljs-string\">'ubuntu-latest'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Azure DevOps supports various agents such as <strong>Microsoft-hosted agents<\/strong> (Linux, Windows, macOS) or <strong>self-hosted agents<\/strong>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Steps<\/strong>:<\/h4>\n\n\n\n<p>Each pipeline is made of <strong>steps<\/strong>. These can be scripts or tasks.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Script<\/strong>: Custom commands.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">steps:\n  - script: <span class=\"hljs-keyword\">echo<\/span> Hello, World!\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>Task<\/strong>: Predefined tasks like build, test, or deploy.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">steps<\/span>:\n  <span class=\"hljs-selector-tag\">-<\/span> <span class=\"hljs-selector-tag\">task<\/span>: <span class=\"hljs-selector-tag\">DotNetCoreCLI<\/span><span class=\"hljs-keyword\">@2<\/span>\n    <span class=\"hljs-attribute\">inputs:<\/span>\n      <span class=\"hljs-attribute\">command:<\/span> <span class=\"hljs-string\">'build'<\/span>\n      <span class=\"hljs-attribute\">projects:<\/span> <span class=\"hljs-string\">'**\/*.csproj'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>4. Advanced Features in Azure Pipelines<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Multi-Stage Pipelines (CI\/CD)<\/strong>:<\/h4>\n\n\n\n<p>Multi-stage pipelines split the build, test, and deployment phases across multiple stages. Each stage can be executed sequentially or in parallel.<\/p>\n\n\n\n<p>Example:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">stages:\n  - stage: Build\n    jobs:\n      - job: BuildJob\n        steps:\n          - script: <span class=\"hljs-keyword\">echo<\/span> Building...\n\n  - stage: Deploy\n    dependsOn: Build\n    jobs:\n      - job: DeployJob\n        steps:\n          - script: <span class=\"hljs-keyword\">echo<\/span> Deploying...\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Environments and Approvals<\/strong>:<\/h4>\n\n\n\n<p>Environments in Azure Pipelines represent the different deployment environments (e.g., Dev, QA, Prod). You can set up approvals for sensitive environments like Production.<\/p>\n\n\n\n<p>Example:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">environments:\n  - name: <span class=\"hljs-string\">'production'<\/span>\n    <span class=\"hljs-attr\">resourceName<\/span>: <span class=\"hljs-string\">'ProdEnvironment'<\/span>\n    <span class=\"hljs-attr\">approval<\/span>:\n      steps:\n        - approval: Manual\n          <span class=\"hljs-attr\">approvers<\/span>:\n            - user@company.com\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Conditional Logic<\/strong>:<\/h4>\n\n\n\n<p>You can set conditions in the pipeline to determine when certain steps or stages should run. Example:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">- script: <span class=\"hljs-keyword\">echo<\/span> This runs only on main branch\n  condition: eq(variables&#91;<span class=\"hljs-string\">'Build.SourceBranch'<\/span>], <span class=\"hljs-string\">'refs\/heads\/main'<\/span>)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>5. Pipeline Testing Strategies<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Unit Tests<\/strong>:<\/h4>\n\n\n\n<p>Run unit tests in your pipeline to ensure that changes do not break the application. Example for .NET Core:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">steps<\/span>:\n  <span class=\"hljs-selector-tag\">-<\/span> <span class=\"hljs-selector-tag\">task<\/span>: <span class=\"hljs-selector-tag\">DotNetCoreCLI<\/span><span class=\"hljs-keyword\">@2<\/span>\n    <span class=\"hljs-attribute\">inputs:<\/span>\n      <span class=\"hljs-attribute\">command:<\/span> <span class=\"hljs-string\">'test'<\/span>\n      <span class=\"hljs-attribute\">projects:<\/span> <span class=\"hljs-string\">'**\/*.Tests.csproj'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\"><strong>Code Coverage<\/strong>:<\/h4>\n\n\n\n<p>You can integrate code coverage tools like Cobertura or JaCoCo to report on how much of your code is covered by tests. Example (JaCoCo for Java projects):<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">steps<\/span>:\n  <span class=\"hljs-selector-tag\">-<\/span> <span class=\"hljs-selector-tag\">task<\/span>: <span class=\"hljs-selector-tag\">Maven<\/span><span class=\"hljs-keyword\">@3<\/span>\n    <span class=\"hljs-attribute\">inputs:<\/span>\n      <span class=\"hljs-attribute\">goals:<\/span> <span class=\"hljs-string\">'verify'<\/span>\n      <span class=\"hljs-attribute\">options:<\/span> <span class=\"hljs-string\">'-Djacoco.skip=false'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>6. Continuous Deployment (CD)<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Step 1: Configuring Deployments to Azure<\/strong><\/h4>\n\n\n\n<p>Azure DevOps integrates easily with various deployment platforms such as <strong>Azure App Services<\/strong>, <strong>AKS (Kubernetes)<\/strong>, <strong>Virtual Machines<\/strong>, or <strong>Containers<\/strong>.<\/p>\n\n\n\n<p>Example for deploying to Azure App Service:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">steps<\/span>:\n  <span class=\"hljs-selector-tag\">-<\/span> <span class=\"hljs-selector-tag\">task<\/span>: <span class=\"hljs-selector-tag\">AzureRmWebAppDeployment<\/span><span class=\"hljs-keyword\">@4<\/span>\n    <span class=\"hljs-attribute\">inputs:<\/span>\n      <span class=\"hljs-attribute\">azureSubscription:<\/span> <span class=\"hljs-string\">'&lt;your-service-connection&gt;'<\/span>\n      <span class=\"hljs-attribute\">appName:<\/span> <span class=\"hljs-string\">'&lt;your-app-service-name&gt;'<\/span>\n      <span class=\"hljs-attribute\">package:<\/span> <span class=\"hljs-string\">'$(System.DefaultWorkingDirectory)\/drop\/*.zip'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Step 2: Rolling Back Deployments<\/strong><\/h4>\n\n\n\n<p>If the deployment fails, you can automatically roll back to the previous version by setting rollback conditions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>7. Pipeline Variables &amp; Secrets Management<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Variables<\/strong>:<\/h4>\n\n\n\n<p>Variables in Azure Pipelines allow you to store values that can be reused across multiple steps.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">variables:\n  buildConfiguration: <span class=\"hljs-string\">'Release'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><h4><strong>Secret Variables<\/strong>:<\/h4><p>Sensitive values like API keys can be stored as secret variables.<\/p><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">variables:\n  - name: <span class=\"hljs-string\">'API_KEY'<\/span>\n    value: <span class=\"hljs-string\">'$(API_KEY)'<\/span>  <span class=\"hljs-comment\"># Referenced securely<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>8. Best Practices for Azure DevOps Pipelines<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Use YAML Pipelines<\/strong>: YAML pipelines are easier to version and maintain than classic pipelines.<\/li>\n\n\n\n<li><strong>Break Down Pipelines<\/strong>: Split pipelines into smaller stages for faster feedback.<\/li>\n\n\n\n<li><strong>Parallel Jobs<\/strong>: Use parallel jobs for steps that are independent, reducing pipeline execution time.<\/li>\n\n\n\n<li><strong>Environment-Specific Variables<\/strong>: Use variable groups or pipeline environments for managing configuration values for different environments.<\/li>\n\n\n\n<li><strong>Automate Rollbacks<\/strong>: Implement automatic rollback strategies in case a deployment fails.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>1. Advanced Pipeline Triggers<\/strong><\/h3>\n\n\n\n<p>While basic triggers (CI and scheduled triggers) are common, advanced use cases require more sophisticated triggering mechanisms.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Path-Based Triggers<\/strong>:<\/h4>\n\n\n\n<p>You can configure pipelines to trigger only when changes occur in specific files or directories.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">trigger:\n  branches:\n    <span class=\"hljs-keyword\">include<\/span>:\n      - main\n  paths:\n    <span class=\"hljs-keyword\">include<\/span>:\n      - src<span class=\"hljs-comment\">\/**\n    exclude:\n      - docs\/**\n<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Tag-Based Triggers<\/strong>:<\/h4>\n\n\n\n<p>To trigger pipelines based on Git tags, useful for triggering deployment pipelines after tagging a release.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">trigger:\n  tags:\n    <span class=\"hljs-keyword\">include<\/span>:\n      - v*\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\"><strong>Pipeline Triggering Other Pipelines<\/strong>:<\/h4>\n\n\n\n<p>You can chain multiple pipelines together by triggering one pipeline after another.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">resources:\n  pipelines:\n    - pipeline: buildPipeline\n      <span class=\"hljs-attr\">source<\/span>: <span class=\"hljs-string\">'BuildPipeline'<\/span>\n      <span class=\"hljs-attr\">trigger<\/span>: <span class=\"hljs-literal\">true<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>2. Multi-Stage Pipelines for End-to-End CI\/CD<\/strong><\/h3>\n\n\n\n<p>Multi-stage pipelines are a crucial feature that allows splitting the pipeline into various <strong>build<\/strong>, <strong>test<\/strong>, and <strong>deployment stages<\/strong>. This ensures clear separation of concerns and flexibility in the deployment process.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Example: Multi-Stage CI\/CD Pipeline for a Web Application<\/strong><\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">trigger:\n  branches:\n    <span class=\"hljs-keyword\">include<\/span>:\n      - main\n\nstages:\n  - stage: Build\n    jobs:\n      - job: BuildJob\n        pool:\n          vmImage: <span class=\"hljs-string\">'ubuntu-latest'<\/span>\n        steps:\n          - task: DotNetCoreCLI@<span class=\"hljs-number\">2<\/span>\n            inputs:\n              command: <span class=\"hljs-string\">'build'<\/span>\n              projects: <span class=\"hljs-string\">'**\/*.csproj'<\/span>\n          - task: PublishBuildArtifacts@<span class=\"hljs-number\">1<\/span>\n            inputs:\n              pathToPublish: $(Build.ArtifactStagingDirectory)\n              artifactName: drop\n\n  - stage: Test\n    dependsOn: Build\n    jobs:\n      - job: TestJob\n        pool:\n          vmImage: <span class=\"hljs-string\">'ubuntu-latest'<\/span>\n        steps:\n          - task: DotNetCoreCLI@<span class=\"hljs-number\">2<\/span>\n            inputs:\n              command: <span class=\"hljs-string\">'test'<\/span>\n              projects: <span class=\"hljs-string\">'**\/*.Tests.csproj'<\/span>\n\n  - stage: Deploy\n    dependsOn: Test\n    condition: succeeded()\n    jobs:\n      - job: DeployJob\n        pool:\n          vmImage: <span class=\"hljs-string\">'ubuntu-latest'<\/span>\n        steps:\n          - script: <span class=\"hljs-keyword\">echo<\/span> Deploying to production\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This example demonstrates how to break the pipeline into <strong>build<\/strong>, <strong>test<\/strong>, and <strong>deployment stages<\/strong>, with dependencies and conditions to ensure smooth flow.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Advanced Stage Dependencies<\/strong>:<\/h4>\n\n\n\n<p>You can create complex dependencies between stages using conditions. For example, skip a stage if the previous one fails.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"HTTP\" data-shcb-language-slug=\"http\"><span><code class=\"hljs language-http\"><span class=\"hljs-attribute\">condition<\/span>: always()\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTTP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">http<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>3. Deployment Strategies<\/strong><\/h3>\n\n\n\n<p>Azure Pipelines support a variety of deployment strategies to ensure safe and efficient releases.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Rolling Deployments<\/strong>:<\/h4>\n\n\n\n<p>Rolling deployments gradually replace instances of your service with the new version, reducing downtime.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">steps<\/span>:\n  <span class=\"hljs-selector-tag\">-<\/span> <span class=\"hljs-selector-tag\">task<\/span>: <span class=\"hljs-selector-tag\">AzureRmWebAppDeployment<\/span><span class=\"hljs-keyword\">@4<\/span>\n    <span class=\"hljs-attribute\">inputs:<\/span>\n      <span class=\"hljs-attribute\">azureSubscription:<\/span> <span class=\"hljs-string\">'&lt;subscription&gt;'<\/span>\n      <span class=\"hljs-attribute\">WebAppName:<\/span> <span class=\"hljs-string\">'&lt;app-service&gt;'<\/span>\n      <span class=\"hljs-attribute\">DeploymentMethod:<\/span> <span class=\"hljs-string\">'rolling'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\"><strong>Canary Deployment<\/strong>:<\/h4>\n\n\n\n<p>Canary deployments send a small percentage of traffic to the new version to ensure the changes work as expected before rolling them out entirely.<\/p>\n\n\n\n<p>This often involves external services like <strong>Azure Traffic Manager<\/strong> or custom traffic-routing logic. Integration can be done with custom pipeline logic or by using additional <strong>Azure App Services<\/strong> for traffic splitting.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>4. Pipeline Templates for Reusability<\/strong><\/h3>\n\n\n\n<p>For teams working on multiple pipelines, it is useful to create templates that can be reused across pipelines. Templates allow you to define jobs, steps, or entire pipelines that can be imported into other pipelines.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Pipeline Template Example<\/strong>:<\/h4>\n\n\n\n<p>Define a reusable build step:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\"># templates\/build-template.yml<\/span>\nparameters:\n  - name: buildConfiguration\n    type: string\n    <span class=\"hljs-keyword\">default<\/span>: <span class=\"hljs-string\">'Release'<\/span>\n\nsteps:\n  - script: |\n      <span class=\"hljs-keyword\">echo<\/span> Build project in ${{ parameters.buildConfiguration }} mode.\n      dotnet build --configuration ${{ parameters.buildConfiguration }}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Using the Template<\/strong>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\"># azure-pipelines.yml<\/span>\nstages:\n  - stage: Build\n    jobs:\n      - template: templates\/build-template.yml\n        parameters:\n          buildConfiguration: <span class=\"hljs-string\">'Debug'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>5. Advanced Environment Management &amp; Approvals<\/strong><\/h3>\n\n\n\n<p>Azure DevOps pipelines support <strong>environments<\/strong> that represent different stages in the deployment lifecycle (e.g., Dev, QA, Staging, Production).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Defining Environments<\/strong>:<\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">environments:\n  - name: <span class=\"hljs-string\">'production'<\/span>\n    <span class=\"hljs-attr\">resourceName<\/span>: <span class=\"hljs-string\">'ProdAppService'<\/span>\n    <span class=\"hljs-attr\">protectionRules<\/span>:\n      - approvals:\n          steps:\n            - approvers: &#91;user1@company.com, user2@company.com]\n              <span class=\"hljs-attr\">timeoutInMinutes<\/span>: <span class=\"hljs-number\">30<\/span>\n              <span class=\"hljs-attr\">approvalType<\/span>: <span class=\"hljs-string\">'Manual'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This ensures that any deployment to production requires a manual approval from specified stakeholders.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Advanced Approvals and Gates<\/strong>:<\/h4>\n\n\n\n<p>Gates provide checks that must be passed before deployment can proceed. This can include external APIs, system health checks, or compliance scans.<\/p>\n\n\n\n<p>Example of using a REST API gate:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">gates:\n  - gate: RestApiGate\n    <span class=\"hljs-attr\">inputs<\/span>:\n      method: GET\n      <span class=\"hljs-attr\">url<\/span>: <span class=\"hljs-string\">'https:\/\/healthcheck.yourdomain.com\/api\/status'<\/span>\n      <span class=\"hljs-attr\">successCriteria<\/span>: eq(root&#91;<span class=\"hljs-string\">'status'<\/span>], <span class=\"hljs-string\">'healthy'<\/span>)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>6. Secret and Secure File Management<\/strong><\/h3>\n\n\n\n<p>Handling sensitive data is critical in CI\/CD pipelines. Azure DevOps offers <strong>Azure Key Vault<\/strong> integration to securely manage secrets and credentials.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Accessing Secrets from Azure Key Vault<\/strong>:<\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">variables:\n  - group: MyVariableGroup\n  - name: <span class=\"hljs-string\">'API_KEY'<\/span>\n    <span class=\"hljs-attr\">value<\/span>: $(API_KEY)\n  - name: <span class=\"hljs-string\">'KEY_VAULT_SECRET'<\/span>\n    <span class=\"hljs-attr\">value<\/span>: $(MySecret)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>7. Parallel Jobs &amp; Matrix Builds<\/strong><\/h3>\n\n\n\n<p>In many cases, especially when working on large projects, running builds in parallel can significantly reduce build time.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Matrix Builds<\/strong>:<\/h4>\n\n\n\n<p>Matrix builds allow you to run the same job with different configurations in parallel.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">strategy:\n  matrix:\n    Linux:\n      vmImage: <span class=\"hljs-string\">'ubuntu-latest'<\/span>\n      <span class=\"hljs-attr\">configuration<\/span>: <span class=\"hljs-string\">'Debug'<\/span>\n    <span class=\"hljs-attr\">Windows<\/span>:\n      vmImage: <span class=\"hljs-string\">'windows-latest'<\/span>\n      <span class=\"hljs-attr\">configuration<\/span>: <span class=\"hljs-string\">'Release'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>8. Pipeline Caching and Artifacts<\/strong><\/h3>\n\n\n\n<p>Azure Pipelines support caching to reduce pipeline run times by storing dependencies between builds.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Caching Dependencies<\/strong>:<\/h4>\n\n\n\n<pre class=\"wp-block-preformatted\">steps:  - task: Cache@2    inputs:      key: 'npm | \"$(Agent.OS)\" | package-lock.json'      path: 'node_modules'      restoreKeys: |        npm | \"$(Agent.OS)\"<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Using Build Artifacts<\/strong>:<\/h4>\n\n\n\n<p>Artifacts are files or packages generated by your build that can be shared or deployed.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">steps:  - task: PublishBuildArtifacts@1    inputs:      pathToPublish: $(Build.ArtifactStagingDirectory)      artifactName: 'drop'<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>9. Integrating with External Tools<\/strong><\/h3>\n\n\n\n<p>Azure Pipelines can be integrated with third-party services like <strong>Slack<\/strong>, <strong>Jira<\/strong>, or <strong>ServiceNow<\/strong>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Slack Notifications<\/strong>:<\/h4>\n\n\n\n<p>Azure Pipelines can send build notifications directly to your Slack channels.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">steps<\/span>:\n  <span class=\"hljs-selector-tag\">-<\/span> <span class=\"hljs-selector-tag\">task<\/span>: <span class=\"hljs-selector-tag\">SlackNotification<\/span><span class=\"hljs-keyword\">@1<\/span>\n    <span class=\"hljs-attribute\">inputs:<\/span>\n      <span class=\"hljs-attribute\">slackConnection:<\/span> <span class=\"hljs-string\">'MySlackServiceConnection'<\/span>\n      <span class=\"hljs-attribute\">message:<\/span> <span class=\"hljs-string\">'Build completed'<\/span>\n      <span class=\"hljs-attribute\">channel:<\/span> <span class=\"hljs-string\">'#devops'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\"><strong>0. Optimizing Pipeline Performance<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Best Practices<\/strong>:<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Use Hosted Agents for Speed<\/strong>: Leverage Microsoft-hosted agents for faster setup and execution, or use self-hosted agents for specialized environments.<\/li>\n\n\n\n<li><strong>Limit Resource Usage<\/strong>: Avoid unnecessary resource allocation by using pipeline stages and jobs efficiently.<\/li>\n\n\n\n<li><strong>Parallel Execution<\/strong>: Run independent jobs in parallel to speed up builds.<\/li>\n\n\n\n<li><strong>Cache External Dependencies<\/strong>: Use caching for dependencies like npm, NuGet, or Docker images.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Resource Limiting<\/strong>:<\/h4>\n\n\n\n<p>To prevent resource waste:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">jobs:\n  - job: Build\n    <span class=\"hljs-attr\">pool<\/span>:\n      vmImage: <span class=\"hljs-string\">'ubuntu-latest'<\/span>\n    <span class=\"hljs-attr\">timeoutInMinutes<\/span>: <span class=\"hljs-number\">20<\/span>\n    <span class=\"hljs-attr\">cancelTimeoutInMinutes<\/span>: <span class=\"hljs-number\">5<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>","protected":false},"excerpt":{"rendered":"<p>Here is an in-depth, step-by-step tutorial on Azure DevOps Pipelines that covers everything from the fundamentals to advanced concepts. This guide is designed to help you understand&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-47122","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/47122","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=47122"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/47122\/revisions"}],"predecessor-version":[{"id":47125,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/47122\/revisions\/47125"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=47122"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=47122"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=47122"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}