Author : MD TAREQ HASSAN | Updated : 2021/10/27
Overview
- Pipelines within Azure DevOps is the CI/CD tool that allows the building, testing and deployment of code using DevOps practices
- Azure Pipelines provide build and release services to support continuous integration (CI) and continuous delivery (CD) of your apps
- Azure Pipelines combines CI and CD to constantly and consistently test and build your code and ship it to any target
- Defined in YAML file
- Code can be pulled from Azure Repos or external repo (i.e. GitHub)
- Run tests during pipeline
- Create reports within pipeline
- Publish artifacts
About multi stage pipeline
- A Multi-Stage YAML Pipeline represents the entire pipeline from CI to the deployments to each environment as a YAML code file
- YAML file essentially replaces what both the Builds and Releases accomplishes
- Single yaml file ‘
azure-pipelines.yml
’ - Contains multiple stages
- CI stage
- CD stage
Visual Studio project setup
- Scaffold Visual Studio projects
- Add
azure-pipelines.yml
to your project - Commit and push
Alternatively, download sample projects from my Github repository: https://github.com/hovermind/AzureDevOpsYamlPipelineDemos
Prerequisites
- Create ACR service connection
- Create AKS environment resource
- AcrPull role, variable groups and pipeline variables
Create pipeline
- Azure DevOps portal > Pipelines > new pipeline
- Create pipeline from existing yaml file
azure-pipelines.yml
trigger:
- master
pool:
vmImage: ubuntu-latest
variables:
- group: 'xyz-api-vg'
stages:
# Continuous Integration Stage
- stage: ci
displayName: CI Stage
jobs:
- job: build_job
displayName: Build Job
steps:
- task: UseDotNet@2
displayName: Use .Net 6.x
inputs:
packageType: 'sdk'
version: '6.x'
- task: DotNetCoreCLI@2
displayName: 'DotNet Restore Before Build'
inputs:
command: 'restore'
projects: '**/XyzAPI/*.csproj'
- task: DotNetCoreCLI@2
displayName: 'DotNet Build'
inputs:
command: 'build'
arguments: '--no-restore'
projects: '**/XyzAPI/*.csproj'
- job: test_job
displayName: Test Job
dependsOn: build_job
condition: succeeded('build_job')
steps:
- task: UseDotNet@2
displayName: Use .Net 6.x
inputs:
packageType: 'sdk'
version: '6.x'
- task: DotNetCoreCLI@2
displayName: 'DotNet Restore Before Test'
inputs:
command: 'restore'
projects: '**/XyzAPI.Test/*.csproj'
- task: DotNetCoreCLI@2
displayName: 'DotNet Test'
inputs:
command: 'test'
arguments: '--no-restore'
projects: '**/XyzAPI.Test/*.csproj'
publishTestResults: true
# Continuous Deployment Stage
- stage: cd
displayName: CD Stage
dependsOn: ci
jobs:
- job: buildAndPushDockerImageJob
displayName: Build & Push Docker Image Job
steps:
- task: UseDotNet@2
displayName: Use .Net 6.x
inputs:
packageType: 'sdk'
version: '6.x'
- task: Docker@2
displayName: Build & Push XyzAPI Image to ACR
inputs:
containerRegistry: AcrServiceConnectionXyzAPI
repository: 'xyz-api'
command: buildAndPush
Dockerfile: '**/XyzAPI/Dockerfile'
buildContext: $(Build.Repository.LocalPath)
tags: $(Build.BuildId)
- deployment: deployToAKS
displayName: Deploy to AKS
dependsOn: buildAndPushDockerImageJob
environment: 'AKSDemoEnvironment.devops-demo'
strategy:
runOnce:
deploy:
steps:
- powershell: |
'# service
apiVersion: v1
kind: Service
metadata:
name: $(appName)
namespace: $(targetNamespace)
labels:
app: $(appName)
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: $(appName)
---
# deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: $(appName)
namespace: $(targetNamespace)
labels:
app: $(appName)
spec:
replicas: 3
selector:
matchLabels:
app: $(appName)
template:
metadata:
labels:
app: $(appName)
spec:
containers:
- name: $(appName)
image: $(acrName).azurecr.io/$(repositoryName):$(Build.BuildId)
ports:
- name: http
containerPort: 80
protocol: TCP
env:
- name: API_BASE_URI
value: $(apiBaseUri)
---
# ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: $(appName)
namespace: $(targetNamespace)
annotations:
kubernetes.io/ingress.class: azure/application-gateway
appgw.ingress.kubernetes.io/backend-path-prefix: "/api/$(apiBaseUri)/"
spec:
rules:
- host: $(appGwDnsUrl)
http:
paths:
- path: /api/$(apiBaseUri)/*
pathType: Prefix
backend:
service:
name: $(appName)
port:
number: 80' | Set-Content $(Agent.TempDirectory)/manifest.yaml
displayName: 'Generate K8s Manifest file'
- task: KubernetesManifest@0
displayName: 'Deploy K8s Manifest to AKS'
inputs:
action: deploy
manifests: '$(Agent.TempDirectory)/manifest.yaml'
Links
- https://docs.microsoft.com/en-us/azure/devops/pipelines/get-started/multi-stage-pipelines-experience
- https://devblogs.microsoft.com/premier-developer/azure-devops-pipelines-multi-stage-pipelines-and-yaml-for-continuous-delivery/
- https://docs.microsoft.com/en-us/azure/devops/pipelines/get-started/what-is-azure-pipelines