Je pars sur une application .NET (ASP.NET Core) déployée sur Azure App Service, avec Azure DevOps pour le pipeline. Si ta stack est différente (conteneurs, Functions, AKS), l’approche reste la même, seules les tâches de déploiement changent.
Architecture
Visual Studio → Azure Repos (ou GitHub) → Azure Pipelines │ Build + Tests → Artefact → Staging (slot) → Approbation → Swap vers Production │ Application Insights
Étape 1 : Préparer le projet dans Visual Studio
- Ouvre ta solution et ajoute un projet de tests (xUnit ou NUnit). Vérifie que tout passe dans Test Explorer.
- Ajoute un endpoint de santé, utile pour les smoke tests :
builder.Services.AddHealthChecks();// ...app.MapHealthChecks("/health"); - Crée le dépôt Git : menu Git → Create Git Repository, puis choisis Azure DevOps ou GitHub et pousse le code.
Étape 2 : Créer les ressources Azure
Avec Azure CLI (ou le portail) :
az loginaz group create -n rg-monapp -l canadaeastaz appservice plan create -n plan-monapp -g rg-monapp --sku S1az webapp create -n monapp-web -g rg-monapp -p plan-monapp --runtime "dotnet:8"az webapp deployment slot create -n monapp-web -g rg-monapp --slot staging
Points importants :
- Les slots de déploiement demandent un plan Standard (S1) ou supérieur.
- Adapte le nom
monapp-web, qui doit être unique mondialement. Vérifie les runtimes disponibles avecaz webapp list-runtimes. - Ajoute Application Insights (créé avec le Web App ou séparément) pour le monitoring.
Étape 3 : Configurer Azure DevOps
- Crée un projet sur dev.azure.com.
- Project Settings → Service connections → New → Azure Resource Manager. Choisis l’authentification Workload identity federation (recommandée, sans secret à gérer) et limite la portée au groupe de ressources
rg-monapp. Nomme-lasc-azure-prod. - Pipelines → Environments : crée
stagingetproduction. - Sur
production, ajoute une Approval check (toi ou ton équipe).
À noter : les agents hébergés par Microsoft peuvent nécessiter une demande de parallélisme gratuit sur les nouvelles organisations. Vérifie ce point dans les paramètres de ton organisation si le pipeline reste en attente.
Étape 4 : Le pipeline azure-pipelines.yml
À la racine du dépôt :
trigger: branches: include: [main]pr: branches: include: [main]pool: vmImage: 'ubuntu-latest'variables: buildConfiguration: 'Release' azureSubscription: 'sc-azure-prod' webAppName: 'monapp-web' resourceGroup: 'rg-monapp'stages:# ---------- CI ----------- stage: Build jobs: - job: BuildTest steps: - task: UseDotNet@2 inputs: packageType: sdk version: '8.x' - task: DotNetCoreCLI@2 displayName: Restore inputs: command: restore projects: '**/*.csproj' - task: DotNetCoreCLI@2 displayName: Build inputs: command: build projects: '**/*.csproj' arguments: '--configuration $(buildConfiguration) --no-restore' - task: DotNetCoreCLI@2 displayName: Tests unitaires inputs: command: test projects: '**/*Tests.csproj' arguments: '--configuration $(buildConfiguration) --no-build --collect:"XPlat Code Coverage"' - task: DotNetCoreCLI@2 displayName: Publish inputs: command: publish publishWebProjects: true arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)' zipAfterPublish: true - publish: $(Build.ArtifactStagingDirectory) artifact: drop# ---------- CD : Staging ----------- stage: DeployStaging dependsOn: Build condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) jobs: - deployment: Staging environment: staging strategy: runOnce: deploy: steps: - task: AzureWebApp@1 displayName: Déploiement dans le slot staging inputs: azureSubscription: $(azureSubscription) appType: webApp appName: $(webAppName) deployToSlotOrASE: true resourceGroupName: $(resourceGroup) slotName: staging package: $(Pipeline.Workspace)/drop/**/*.zip - script: | sleep 20 curl --fail --retry 5 --retry-delay 10 https://$(webAppName)-staging.azurewebsites.net/health displayName: Smoke test# ---------- CD : Production ----------- stage: DeployProd dependsOn: DeployStaging jobs: - deployment: Production environment: production # déclenche l'approbation manuelle strategy: runOnce: deploy: steps: - task: AzureAppServiceManage@0 displayName: Swap staging vers production inputs: azureSubscription: $(azureSubscription) Action: 'Swap Slots' WebAppName: $(webAppName) ResourceGroupName: $(resourceGroup) SourceSlot: staging SwapWithProduction: true
Puis dans Azure DevOps : Pipelines → New pipeline → Azure Repos Git → Existing YAML file.
Étape 5 : Protéger la branche main
Repos → Branches → main → Branch policies :
- Revue de code obligatoire (1 reviewer minimum).
- Build validation : le pipeline doit réussir avant de pouvoir fusionner une PR.
- Résolution des commentaires obligatoire.
Résultat : les PR lancent le build et les tests (étape CI uniquement), et seul un merge sur main déclenche le déploiement.
Étape 6 : Gérer les secrets et la configuration
- Azure Key Vault pour les mots de passe, chaînes de connexion et clés d’API. Donne à l’App Service une Managed Identity et référence les secrets avec
@Microsoft.KeyVault(SecretUri=...)dans les paramètres de l’application. - Utilise des paramètres de slot (« Deployment slot setting ») pour les valeurs propres à chaque environnement.
- Ne mets jamais de secrets dans le dépôt ni dans le YAML.
Étape 7 : Monitoring et retour arrière
- Application Insights pour les requêtes, erreurs, dépendances et performances. Configure des alertes (taux d’erreur, temps de réponse).
- Rollback instantané : refais un swap des slots. L’ancienne version est toujours dans le slot
stagingaprès le swap.
Alternative : le raccourci depuis Visual Studio
Dans Visual Studio, clic droit sur le projet → Publish → Azure → Azure App Service. L’assistant peut proposer de générer un workflow GitHub Actions (CI/CD) avec les identifiants Azure déjà configurés. C’est très rapide pour démarrer, mais moins complet qu’un pipeline en plusieurs étapes avec approbations. Garde-le pour un prototype, et utilise le pipeline YAML ci-dessus pour un projet sérieux.
Évolutions possibles
- Infrastructure as Code : décrire les ressources Azure avec Bicep ou Terraform plutôt qu’avec des commandes manuelles.
- Scans de sécurité : Defender for DevOps, CodeQL, scan de dépendances.
- Conteneurs : build d’image Docker, push vers Azure Container Registry, déploiement sur App Service for Containers ou Azure Container Apps.
- Déploiement canary : le « Testing in production » des slots permet de router un pourcentage du trafic vers
stagingavant le swap.