Introduction
Azure Pipelines, service CI/CD d'Azure DevOps, révolutionne les workflows DevOps en 2026 avec un support YAML natif ultra-flexible. Contrairement aux pipelines classiques UI-only, les YAML permettent versionning Git, réutilisabilité et approches IaC (Infrastructure as Code). Ce tutoriel expert vous guide pas à pas pour un pipeline complet sur un projet Node.js : build multi-OS, tests parallèles avec matrice, publication d'artefacts, et déploiements sécurisés vers Azure App Service via environnements avec approvals manuelles.
Pourquoi c'est crucial ? En prod, 70% des échecs CI/CD viennent de configs non versionnées ou non testées. Ici, on implémente triggers intelligents, conditions runtime, secrets Azure Key Vault, et monitoring intégré. Résultat : pipelines scalables pour équipes enterprise, réduisant le MTTR (Mean Time To Recovery) de 50%. Prêt à bookmarker ce guide référence ? (142 mots)
Prérequis
- Compte Azure DevOps gratuit (dev.azure.com)
- Projet Node.js avec package.json, tests Jest, et Dockerfile (clonez ce repo exemple)
- Azure Subscription avec App Service créé
- Azure CLI installé et connecté (
az login) - Connaissances avancées en YAML, Git, et DevOps (niveau senior)
- Service connection 'AzureRM' dans Azure DevOps Project Settings > Service connections
Pipeline basique : Build et tests
trigger:
branches:
include:
- main
- develop
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: Build
jobs:
- job: BuildJob
steps:
- task: NodeTool@0
inputs:
versionSpec: '20.x'
- script: npm ci
displayName: 'Install dependencies'
- script: npm run build
displayName: 'Build app'
- script: npm test
displayName: 'Run tests'
env:
CI: trueCe pipeline YAML déclenche sur main/develop, utilise un agent Ubuntu, installe Node 20, dépendances, build et tests. Piège : Oublier 'npm ci' pour installs reproductibles en CI ; ici, on force --frozen-lockfile implicitement. Copiez-collez directement à la racine de votre repo Git.
Comprendre les triggers et pools
Les triggers automatisent les runs sur pushes/merge. Ici, limités à main/develop pour éviter spam sur features. Pools sélectionnent l'agent : 'ubuntu-latest' pour Linux prod ; alternez avec 'windows-latest' pour cross-platform.
Analogie : triggers = sentinelles Git, pools = fermes d'agents cloud scalables (Microsoft-hosted, gratuits jusqu'à 1800 min/mois). Prochaine étape : paralléliser avec matrices pour tests multi-OS/arch.
Matrice jobs : Tests multi-plateforme
trigger:
branches:
include:
- main
- develop
stages:
- stage: Test
jobs:
- job: TestMatrix
strategy:
matrix:
Node18Ubuntu:
nodeVersion: '18.x'
image: 'ubuntu-20.04'
Node20Windows:
nodeVersion: '20.x'
image: 'windows-2022'
pool:
vmImage: $(image)
steps:
- task: NodeTool@0
inputs:
versionSpec: $(nodeVersion)
- script: |
npm ci
npm test -- --coverage
displayName: 'Tests with coverage'Ajout d'une matrice strategy : exécute jobs en parallèle pour Node 18/Ubuntu et 20/Windows. Variables runtime $(nodeVersion) injectées. Piège : Matrice trop large explose minutes ; limitez à 4-6 combos. Intégrez à votre pipeline existant en remplaçant la stage Test.
Stratégies de parallélisme
La matrice multiplie jobs sans duplication YAML, idéal pour browsers (Chrome/Firefox) ou OS. Conditions : condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) pour runs sélectifs.
Avantage expert : Fan-out/fan-in réduit temps total de 70% vs jobs séquentiels. Suivant : variables sécurisées et artefacts.
Variables, secrets et artefacts
variables:
npm-config-name: 'my-azure-app'
system.debug: true # Pour logs verbose
stages:
- stage: Publish
dependsOn: Test
jobs:
- job: PublishArtifact
steps:
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: 'dist'
artifactName: 'app-build'
- task: PublishNpmAuthToken@1 # Nécessite secret NPM_TOKEN
inputs:
npmAuthToken: $(NPM_TOKEN) # Variable secrète Pipelines
- script: npm publish --access public
env:
NPM_TOKEN: $(NPM_TOKEN)
resources:
repositories:
- repository: templates
type: github
name: learni-dev/pipeline-templates
endpoint: github-serviceVariables globales + secrets (ajoutez NPM_TOKEN en Pipelines > Library > Variable groups). Publie artefacts 'dist' et package NPM. Resources réutilisent templates GitHub. Piège : Secrets exposés en logs si !system.debug absent ; utilisez Key Vault pour prod.
Gestion des secrets et réutilisabilité
Variable groups + Key Vault : Liez via azureSubscription pour rotation auto. Templates (resources.repositories) factorisent steps communs, comme lint/test.
Analogie : Variables = params fonctions, templates = libs npm. Prochain : déploiements multi-env avec approvals.
Déploiement multi-stage avec environments
stages:
- stage: DeployStaging
dependsOn: Publish
condition: eq(variables['Build.SourceBranch'], 'refs/heads/develop')
jobs:
- deployment: DeployToStaging
environment: 'staging' # Créez en Environments UI
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
inputs:
azureSubscription: 'AzureRM-ServiceConnection'
appType: 'webAppLinux'
appName: 'myapp-staging'
package: $(Pipeline.Workspace)/app-build/drop/**/dist.zip
- stage: DeployProd
dependsOn: DeployStaging
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: DeployToProd
environment: 'production' # Avec manual approval
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: app-build
- task: AzureWebApp@1
inputs:
appName: 'myapp-prod'Jobs deployment avec environment 'staging/prod' (UI: Pipelines > Environments, ajoutez approbations). Download artefact précédent. Conditions branch-specific. Piège : Oublier 'download: current' = déploiement vide ; testez manuellement via 'Run pipeline'.
Environnements et gates
Environnements = checkpoints avec checks (approvals, invokes, gates comme API health). Gates = queries asynchrones (ex: 'API up?').
Expert tip : Intégrez SonarQube via task@5 pour SAST, fail fast si qualité < A.
Pipeline complet avec Docker et Helm
stages:
- stage: DockerBuild
jobs:
- job: BuildPush
steps:
- task: Docker@2
inputs:
command: buildAndPush
repository: myacr.azurecr.io/myapp
dockerfile: Dockerfile
containerRegistry: 'my-acr-connection'
tags: |
$(Build.BuildId)
latest
- stage: HelmDeploy
dependsOn: DockerBuild
deployment: K8sDeploy
environment: 'aks-prod'
strategy:
runOnce:
deploy:
steps:
- task: HelmDeploy@0
inputs:
connectionType: 'Azure Resource Manager'
azureSubscription: 'AzureRM'
azureResourceGroup: 'my-rg'
kubernetesNamespace: 'default'
command: 'upgrade'
chartType: 'FilePath'
chartPath: 'helm/myapp'
releaseName: 'myapp'
valueFile: 'values-prod.yaml'Build/push Docker vers ACR, puis Helm upgrade sur AKS. Nécessite service connections ACR/AKS. Tags dynamiques $(Build.BuildId). Piège : Helm sans 'upgrade --install' recreuse ; ajoutez --install en prod. Intégrez comme stage final.
Bonnes pratiques
- Versionnez YAML en Git : Pas de UI edits !
- Templates obligatoires : Réutilisez 80% steps via extends.
- Self-hosted agents pour secrets/high-perf (ex: GPU ML).
- Conditions everywhere :
dependsOn+condition: succeededOrFailed()pour cleanup. - Caching :
Cache@2pour node_modules (hash: package-lock.json) = x10 vitesse.
Erreurs courantes à éviter
- Checkout shallow :
fetchDepth: 0pour history complet (LFS/git submodules). - Secrets en logs : Toujours
$(var)pas ${{ }} (compile-time vs runtime). - No parallel limits : Cap à 10 jobs free tier ; utilisez
maxParallel: 4. - Envs sans checks : Ajoutez mandatory approvers sinon bypass.
Pour aller plus loin
Plongez dans Azure Pipelines docs officielles. Intégrez GitHub Actions hybrid via multi-cloud.
Découvrez nos formations DevOps Learni : Azure Architect certifiante, hands-on Pipelines enterprise. Rejoignez la communauté Discord pour Q&A live.