Skip to main content

Azure Pipelines


1 - Overview

Azure Pipelines lets you create CI/CD pipelines to build, test, and deploy your applications.


2 - Pipeline types

# azure-pipelines.yml
trigger:
- main

pool:
vmImage: 'ubuntu-latest'

steps:
- script: echo Hello, world!
displayName: 'Run a one-line script'

2.2 Classic Pipelines (GUI)

A graphical interface for creating pipelines without YAML.

  • Useful for getting started quickly
  • Less version control
  • Being deprecated for new projects

3 - Agents

3.1 Microsoft-hosted agents

ImageOSUsage
ubuntu-latestUbuntu 22.04Linux builds
windows-latestWindows Server 2022.NET, Windows
macos-latestmacOS 13iOS, macOS

3.2 Self-hosted agents

# Télécharger l'agent
wget https://vstsagentpackage.azureedge.net/agent/3.230.0/vsts-agent-linux-x64-3.230.0.tar.gz
tar zxvf vsts-agent-linux-x64-3.230.0.tar.gz

# Configurer
./config.sh

# Lancer comme service
sudo ./svc.sh install
sudo ./svc.sh start

3.3 Comparison

AspectMicrosoft-hostedSelf-hosted
MaintenanceNoneYou manage
CostPay-per-minuteInfrastructure
CustomizationLimitedTotal
Private networkNoYes
CacheNot persistentPersistent

4 - Build Pipeline

4.1 Node.js pipeline

trigger:
branches:
include:
- main
- develop
paths:
exclude:
- README.md

pool:
vmImage: 'ubuntu-latest'

variables:
NODE_VERSION: '18.x'

stages:
- stage: Build
jobs:
- job: BuildJob
steps:
- task: NodeTool@0
inputs:
versionSpec: $(NODE_VERSION)
displayName: 'Install Node.js'

- script: npm ci
displayName: 'Install dependencies'

- script: npm run lint
displayName: 'Lint'

- script: npm run build
displayName: 'Build'

- script: npm test -- --coverage
displayName: 'Test'

- task: PublishTestResults@2
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '**/junit.xml'

- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: 'Cobertura'
summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage/cobertura-coverage.xml'

- task: PublishBuildArtifacts@1
inputs:
pathToPublish: 'dist'
artifactName: 'app'

4.2 .NET pipeline

trigger:
- main

pool:
vmImage: 'windows-latest'

variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'

steps:
- task: NuGetToolInstaller@1

- task: NuGetCommand@2
inputs:
restoreSolution: '$(solution)'

- task: VSBuild@1
inputs:
solution: '$(solution)'
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'

- task: VSTest@2
inputs:
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'

4.3 Docker pipeline

trigger:
- main

pool:
vmImage: 'ubuntu-latest'

variables:
dockerRegistry: 'myacr.azurecr.io'
imageName: 'myapp'
tag: '$(Build.BuildId)'

steps:
- task: Docker@2
inputs:
containerRegistry: 'ACR-Connection'
repository: '$(imageName)'
command: 'buildAndPush'
Dockerfile: '**/Dockerfile'
tags: |
$(tag)
latest

5 - Release Pipeline

5.1 Environments

# Définir des environments dans le pipeline
stages:
- stage: DeployDev
jobs:
- deployment: Deploy
environment: 'Development'
strategy:
runOnce:
deploy:
steps:
- script: echo Deploying to Dev

- stage: DeployProd
dependsOn: DeployDev
jobs:
- deployment: Deploy
environment: 'Production'
strategy:
runOnce:
deploy:
steps:
- script: echo Deploying to Prod

5.2 Approvals and Gates

Configure in Environments → Production → Approvals and checks:

  • Approvals: Manual validation
  • Branch control: Deploy only from main
  • Business hours: Deploy during business hours
  • Invoke Azure Function: Custom check

5.3 Deployment strategies

# Rolling deployment
strategy:
rolling:
maxParallel: 2
preDeploy:
steps:
- script: echo Pre-deploy
deploy:
steps:
- script: echo Deploying
on:
failure:
steps:
- script: echo Rollback

# Canary deployment
strategy:
canary:
increments: [10, 20]
preDeploy:
steps:
- script: echo Pre-deploy
deploy:
steps:
- script: echo Deploying $(strategy.increment)%

6 - Common tasks

6.1 Copy Files

- task: CopyFiles@2
inputs:
sourceFolder: '$(Build.SourcesDirectory)/dist'
contents: '**'
targetFolder: '$(Build.ArtifactStagingDirectory)'

6.2 Azure App Service Deploy

- task: AzureWebApp@1
inputs:
azureSubscription: 'Azure-Connection'
appType: 'webAppLinux'
appName: 'my-webapp'
package: '$(Pipeline.Workspace)/app/**/*.zip'

6.3 Kubernetes Deploy

- task: KubernetesManifest@0
inputs:
action: 'deploy'
kubernetesServiceConnection: 'K8s-Connection'
namespace: 'production'
manifests: |
$(Pipeline.Workspace)/manifests/deployment.yml
$(Pipeline.Workspace)/manifests/service.yml
containers: '$(dockerRegistry)/$(imageName):$(tag)'

7 - Variables and secrets

7.1 Pipeline variables

variables:
# Variable simple
buildConfiguration: 'Release'

# Variable depuis un groupe
- group: 'my-variable-group'

# Variable conditionnelle
- name: environment
${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}:
value: 'production'
${{ else }}:
value: 'development'

7.2 System variables

VariableDescription
$(Build.BuildId)Unique build ID
$(Build.SourceBranch)Source branch
$(Build.SourcesDirectory)Sources directory
$(Pipeline.Workspace)Pipeline workspace
$(System.DefaultWorkingDirectory)Working directory

7.3 Secrets

# Utiliser un secret depuis une variable group
- script: |
echo "Using secret..."
curl -H "Authorization: Bearer $(API_KEY)" https://api.example.com
env:
API_KEY: $(mySecret)

Summary

In this chapter, we learned:

  • The pipeline types (YAML vs Classic)
  • The agents (Microsoft-hosted vs Self-hosted)
  • Build Pipelines
  • Release Pipelines and environments
  • Common tasks
  • Variables and secrets

Next step

In the next chapter, we will dive deeper into YAML Pipelines.

→ Next chapter: YAML Pipelines


← Back to the table of contents