Skip to main content

Exercises and Projects


1 - Hands-on exercises

Exercise 1: Initial configuration

Objective: Create an Azure DevOps organization and project.

Tasks:

  1. Create an organization on dev.azure.com
  2. Create a "MyApp" project with the Agile process
  3. Initialize a repo with a README
  4. Configure branch policies on main
Solution
# Installer Azure CLI et extension DevOps
az extension add --name azure-devops

# Se connecter
az login
az devops configure --defaults organization=https://dev.azure.com/MonOrg

# Créer le projet
az devops project create --name "MyApp" --process Agile --visibility private

# Configurer le projet par défaut
az devops configure --defaults project=MyApp

# Créer le repo (déjà créé avec le projet)
az repos list

# Configurer branch policy (via l'interface ou API)
# Project Settings > Repos > Policies > main

Exercise 2: CI pipeline

Objective: Create a CI pipeline for a Node.js application.

Solution
# azure-pipelines.yml
trigger:
- main
- develop

pool:
vmImage: 'ubuntu-latest'

variables:
NODE_VERSION: '18.x'

stages:
- stage: Build
jobs:
- job: BuildAndTest
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 --reporters=default --reporters=jest-junit
displayName: 'Test'

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

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

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

Exercise 3: CD pipeline

Objective: Add deployment stages with approvals.

Solution
# Ajouter après le stage Build
stages:
- stage: Build
# ... (voir exercice 2)

- stage: DeployDev
dependsOn: Build
jobs:
- deployment: DeployToDev
environment: 'Development'
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app

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

- stage: DeployProd
dependsOn: DeployDev
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
jobs:
- deployment: DeployToProd
environment: 'Production' # Requires approval
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app

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

Exercise 4: Azure Boards

Objective: Create a sprint with work items.

Solution
# Créer une itération
az boards iteration project create \
--name "Sprint 1" \
--start-date 2024-01-15 \
--finish-date 2024-01-29

# Créer une Epic
az boards work-item create \
--type "Epic" \
--title "Authentication System"

# Créer une Feature
az boards work-item create \
--type "Feature" \
--title "User Login" \
--parent 1

# Créer des User Stories
az boards work-item create \
--type "User Story" \
--title "As a user, I want to login with email/password" \
--parent 2 \
--iteration "MyApp\Sprint 1"

az boards work-item create \
--type "User Story" \
--title "As a user, I want to reset my password" \
--parent 2 \
--iteration "MyApp\Sprint 1"

# Créer des Tasks
az boards work-item create \
--type "Task" \
--title "Create login form UI" \
--parent 3

az boards work-item create \
--type "Task" \
--title "Implement authentication API" \
--parent 3

2 - Complete project: Full Stack Web Application

Architecture

Project structure

my-fullstack-app/
├── .azure/
│ ├── pipelines/
│ │ ├── ci.yml
│ │ ├── cd.yml
│ │ └── templates/
│ │ ├── build-template.yml
│ │ └── deploy-template.yml
│ └── boards/
│ └── work-item-template.json
├── frontend/
│ ├── package.json
│ ├── Dockerfile
│ └── src/
├── backend/
│ ├── package.json
│ ├── Dockerfile
│ └── src/
├── infrastructure/
│ └── kubernetes/
│ ├── deployment.yml
│ └── service.yml
└── README.md

Complete CI pipeline

# .azure/pipelines/ci.yml
trigger:
branches:
include:
- main
- develop
paths:
exclude:
- README.md
- docs/**

pr:
branches:
include:
- main

variables:
- group: 'CI-Variables'
- name: dockerRegistry
value: 'myacr.azurecr.io'

stages:
- stage: Validate
jobs:
- job: Lint
pool:
vmImage: 'ubuntu-latest'
steps:
- script: npm run lint
workingDirectory: frontend
- script: npm run lint
workingDirectory: backend

- stage: Test
dependsOn: Validate
jobs:
- job: FrontendTests
pool:
vmImage: 'ubuntu-latest'
steps:
- template: templates/build-template.yml
parameters:
workingDirectory: 'frontend'
runTests: true

- job: BackendTests
pool:
vmImage: 'ubuntu-latest'
steps:
- template: templates/build-template.yml
parameters:
workingDirectory: 'backend'
runTests: true

- stage: Build
dependsOn: Test
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- job: BuildImages
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Docker@2
inputs:
containerRegistry: 'ACR-Connection'
repository: 'frontend'
command: 'buildAndPush'
Dockerfile: 'frontend/Dockerfile'
tags: |
$(Build.BuildId)
latest

- task: Docker@2
inputs:
containerRegistry: 'ACR-Connection'
repository: 'backend'
command: 'buildAndPush'
Dockerfile: 'backend/Dockerfile'
tags: |
$(Build.BuildId)
latest

CD pipeline

# .azure/pipelines/cd.yml
trigger: none

resources:
pipelines:
- pipeline: CI
source: 'MyApp-CI'
trigger: true

variables:
- group: 'CD-Variables'

stages:
- stage: DeployDev
jobs:
- deployment: Deploy
environment: 'Development'
strategy:
runOnce:
deploy:
steps:
- task: KubernetesManifest@0
inputs:
action: 'deploy'
kubernetesServiceConnection: 'AKS-Dev'
namespace: 'development'
manifests: |
infrastructure/kubernetes/*.yml
containers: |
$(dockerRegistry)/frontend:$(resources.pipeline.CI.runID)
$(dockerRegistry)/backend:$(resources.pipeline.CI.runID)

- stage: DeployStaging
dependsOn: DeployDev
jobs:
- deployment: Deploy
environment: 'Staging'
strategy:
runOnce:
deploy:
steps:
- task: KubernetesManifest@0
inputs:
action: 'deploy'
kubernetesServiceConnection: 'AKS-Staging'
namespace: 'staging'
manifests: |
infrastructure/kubernetes/*.yml

- stage: DeployProduction
dependsOn: DeployStaging
jobs:
- deployment: Deploy
environment: 'Production'
strategy:
canary:
increments: [10, 50]
preDeploy:
steps:
- script: echo "Pre-deploy checks"
deploy:
steps:
- task: KubernetesManifest@0
inputs:
action: 'deploy'
kubernetesServiceConnection: 'AKS-Prod'
namespace: 'production'
manifests: |
infrastructure/kubernetes/*.yml

3 - Review quiz

  1. What is the difference between Azure Repos and GitHub?

  2. What are the 5 services of Azure DevOps?

  3. How do you secure secrets in a pipeline?

  4. What is a branch policy?

  5. How do you configure deployment approvals?

Answers
  1. Azure Repos is the Git service integrated into Azure DevOps, with native integration to the other services. GitHub is an independent platform but can be connected to Azure Pipelines.

  2. Azure Boards, Azure Repos, Azure Pipelines, Azure Artifacts, Azure Test Plans.

  3. Use Variable Groups marked as secrets, Azure Key Vault, or the secrets of Service Connections.

  4. Rules applied to branches (required reviewers, build validation, etc.) to protect the code.

  5. In Environments > Production > Approvals and checks, add Approvals with the approvers.


4 - Microsoft certification

Azure DevOps Engineer Expert (AZ-400)

DomainWeight
Design and implement processes and communications10-15%
Design and implement source control15-20%
Design and implement build and release pipelines40-45%
Develop a security and compliance plan10-15%
Implement an instrumentation strategy10-15%

Resources


Course summary

Congratulations! You have completed the Azure DevOps course.

You now have a firm grasp of:

  • Azure Repos for source control
  • Azure Boards for project management
  • Azure Pipelines for CI/CD
  • Azure Artifacts for packages
  • Azure Test Plans for testing
  • The security best practices

Next steps

  • Practice with real projects
  • Take the AZ-400 certification
  • Explore integrations with Azure Cloud
  • Study GitHub Actions as an alternative

← Back to the table of contents