Skip to content
Learni
View all tutorials
DevOps

How to Set Up an Azure DevOps CI/CD Pipeline in 2026

18 minINTERMEDIATE
Lire en français

Introduction

Azure DevOps enables full automation of the application lifecycle through powerful YAML pipelines. In 2026, multi-stage pipelines with built-in quality controls have become the standard for mature DevOps teams. This tutorial walks you through creating a production-ready CI/CD pipeline for a Node.js application deployed to Azure App Service. You will learn how to structure YAML files, manage variables and secrets, and implement deployment gates.

Prerequisites

  • Azure DevOps account and active Azure subscription
  • Azure CLI installed and configured
  • Basic knowledge of YAML and Docker containers
  • Simple Node.js application ready for deployment

Step 1: Initialize the Repository and Pipeline

Create a new repository in Azure DevOps and add the azure-pipelines.yml file at the root.

Basic Build Pipeline

azure-pipelines.yml
trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

variables:
  azureSubscription: 'MyAzureConnection'
  appName: 'myapp-prod'

stages:
- stage: Build
  jobs:
  - job: Build
    steps:
    - task: NodeTool@0
      inputs:
        versionSpec: '20.x'
    - script: |
        npm ci
        npm run build
      displayName: 'Build application'

This pipeline triggers a build on every push to main. It uses Node 20 and runs the build commands. The Azure connection name must be created manually in the project settings.

Step 2: Add Tests and Code Analysis

Integrate unit tests and SonarQube to ensure quality before any deployment.

Adding Tests and Quality Checks

azure-pipelines.yml
    - script: |
        npm test -- --coverage
      displayName: 'Run tests'
    - task: SonarQubePrepare@5
      inputs:
        SonarQube: 'SonarConnection'
        scannerMode: 'CLI'
        configMode: 'manual'
        cliProjectKey: 'myapp'
    - task: SonarQubeAnalyze@5

Tests run with coverage enabled. SonarQube is configured to analyze the code. The pipeline will automatically fail if quality thresholds are not met.

Step 3: Staging Deployment

Add a deployment stage to the staging environment with manual approval.

Staging Deployment Stage

azure-pipelines.yml
- stage: DeployStaging
  dependsOn: Build
  jobs:
  - deployment: Deploy
    environment: 'staging'
    strategy:
      runOnce:
        deploy:
          steps:
          - task: AzureWebApp@1
            inputs:
              azureSubscription: $(azureSubscription)
              appName: 'myapp-staging'
              package: '$(System.DefaultWorkingDirectory)/dist'

This stage uses the deployment job model with an Azure DevOps environment. It enables manual approvals and gates before production.

Step 4: Production Deployment

Finalize with a protected and conditioned production stage.

Production Stage with Condition

azure-pipelines.yml
- stage: DeployProduction
  dependsOn: DeployStaging
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  jobs:
  - deployment: Deploy
    environment: 'production'
    strategy:
      runOnce:
        deploy:
          steps:
          - task: AzureWebApp@1
            inputs:
              azureSubscription: $(azureSubscription)
              appName: $(appName)
              package: '$(System.DefaultWorkingDirectory)/dist'

The production stage runs only on main and after staging validation. Using variables makes the pipeline reusable across projects.

Step 5: Variables and Secrets

Externalize configuration into pipeline variables and Azure Key Vault.

Variable Configuration

azure-pipelines.yml
variables:
- group: 'myapp-variables'
- name: 'azureSubscription'
  value: 'MyAzureConnection'

steps:
- task: AzureKeyVault@2
  inputs:
    azureSubscription: $(azureSubscription)
    KeyVault: 'myapp-kv'
    SecretsFilter: '*'
    RunAsPreJob: true

Variables are loaded from a shared variable group. Secrets are injected from Key Vault at runtime to avoid storing them in plain text.

Best Practices

  • Always use deployment jobs for deployments
  • Protect main branches with branch policies
  • Externalize all configuration into variable groups
  • Add explicit conditions on production stages
  • Version Docker images with Build.BuildId

Common Mistakes to Avoid

  • Forgetting the branch condition on production deployments
  • Using overly long inline scripts instead of templates
  • Not configuring approvals on critical environments
  • Storing secrets directly in the YAML file

Going Further

Explore our advanced Azure DevOps and YAML pipelines training at learni-group.com/formations.