mohamedradwan.com - Nothing can beat experience
Post
Cancel

Multi-stage CI/CD pipelines as code using YAML and Azure Pipelines Tutorial | Configuring CI/CD Pipelines as Code with YAML

The following video has all the steps on how to do this tutorial:

Intro

You will see a complete tutorial on how to create and configure CI/CD pipelines as code using the YAML configuration language. Also, how to build a multi-stage pipeline which means that we have more than one stage in the same YAML file. We can have build stage, integration test stage, deployment stage, and many more as needed.

Be aware that this tutorial will not cover any infrastructure as code. There are other tutorials on my blog that will do that, like the one with Ansible and the one with Terraform.

In this tutorial, I will use a sample project on GitHub named Pars-Unlimited that is developed in ASP.NET Core.

Pipelines-as-YAML

Creating the infrastructure for the application manually

So, the first step is to start creating the infrastructure for the application manually, since we are not doing it as code. To do that, I will open my Azure portal and create a resource group. I will use a predefined Azure template which will create all the components needed for the infrastructure for the application. This includes an Azure Service Plan, Azure Web App, and SQL Server on Azure. Also, the template will create and configure an Azure firewall rule for Azure SQL, so Azure Web App can have permission to access Azure SQL.

For more information about how to work with Kubernetes cluster and deploy it to Azure Kubernetes Service (AKS) and work with Azure Container Registry, see Kubernetes cluster for beginner

Create a YAML pipeline file

Once I complete that, I will open Azure DevOps and navigate to the Azure pipeline. The first step is to create a YAML pipeline file which is the build pipeline as code, then choose the location where I want to store the file. The YAML file is usually stored in the same repository with the application code. When I create the YAML file, I can choose which YAML template to use. Since my application is an ASP.NET application, I will choose the ASP.NET template, which is a ready-made YAML file for some build tasks for ASP.NET. The template tasks include restoring all the NuGet packages, building the application, running the unit tests, and so on.

Run or kick a continuous integration build

After that, I will run or kick a continuous integration build.

Adding a new pipeline stage to the YAML file

After the build completes, I will open the YAML file again for editing. I will add a new step to start creating the web package.zip, then store that package on Azure DevOps artifacts, then run or kick a new build again. Once the build is complete, I will start editing the YAML file again, then adding a new stage. To create a new stage, I will do that by copying the old stage and renaming it from build to deployment. Then in the deployment stage, I will start adding some new tasks to pick up the web package and deploy that package to the Azure Web App. During the deployment stage, the pipeline will download the web package on the pipeline agent, then deploy that package to the Azure Web App. After that, I will change the connection string of the web app using the connection string from the web.config in my application to make sure that it will be translated correctly.

Browse the application after deploying it to Azure

Then browse the application from the Azure Web App to see the application.

The following is the final YAML file content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# ASP.NET
# Build and test ASP.NET projects
# Add steps that publish symbols, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/apps/aspnet/build-aspnet-4
trigger:
  - master
stages:
  - stage: Build
    jobs:
      - job: Build
        pool:
          vmImage: 'vs2017-win2016'
        variables:
          solution: '**/*.sln'
          buildPlatform: 'Any CPU'
          buildConfiguration: 'Release'
        steps:
          - task: NuGetToolInstaller@1
          - task: NuGetCommand@2
            inputs:
              restoreSolution: '$(solution)'
          - task: VSBuild@1
            inputs:
              solution: '$(solution)'
              msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)"'
              platform: '$(buildPlatform)'
              configuration: '$(buildConfiguration)'
          - task: VSTest@2
            inputs:
              platform: '$(buildPlatform)'
              configuration: '$(buildConfiguration)'
          - task: PublishBuildArtifacts@1
            inputs:
              PathtoPublish: '$(Build.ArtifactStagingDirectory)'
              ArtifactName: 'drop'
              publishLocation: 'Container'
  - stage: Deploy
    jobs:
      - job: Deploy
        pool:
          vmImage: 'vs2017-win2016'
        steps:
          - task: DownloadBuildArtifacts@0
            inputs:
              buildType: 'current'
              downloadType: 'single'
              artifactName: 'drop'
              downloadPath: '$(System.ArtifactsDirectory)'
          - task: CmdLine@2
            inputs:
              script: |
                echo Tell me all folders and file in this path
                dir /b /s
          - task: AzureRmWebAppDeployment@4
            inputs:
              ConnectionType: 'AzureRM'
              azureSubscription: 'Visual Studio Enterprise(ff1d424e-36cd-400a-ba00-d801cb0bf0a4)'
              appType: 'webApp'
              WebAppName: 'WebAppSQLRadwan'
              packageForLinux: '$(System.ArtifactsDirectory)/drop/*.zip'
Trending Tags