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.
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'