Azure DevOps â CI/CD Pipelines Complete Guide
In this tutorial, you'll learn about Azure DevOps. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Azure DevOps is Microsoft's end-to-end DevOps platform providing Git repos, CI/CD pipelines, artifact feeds, test plans, and project boards â all integrated into a single tool for automating software delivery.
What You'll Learn
You'll understand how to create YAML-based CI/CD pipelines in Azure DevOps, configure build and release stages, manage variables and secrets, integrate tests and security scans, and deploy to Azure App Service.
Why Azure DevOps Matters
Manual deployment is error-prone and slow. CI/CD pipelines catch bugs early, enforce code quality gates, and deploy reliably. DodaTech uses Azure DevOps pipelines to build, scan, and deploy Doda Browser updates across Windows, macOS, and Linux simultaneously.
Real-World Use
Every time a developer pushes code to the main branch, a pipeline automatically builds the application, runs 500+ unit and integration tests, scans for vulnerable dependencies, and deploys to a staging environment â all without human intervention.
Azure DevOps Learning Path
flowchart LR A["Version Control (Git)"] --> B["Azure DevOps Overview"] B --> C["YAML Pipelines"] C --> D["Build & Test Stages"] D --> E["Release & Deploy"] E --> F["Monitoring & Feedback"] C:::current classDef current fill:#f90,color:#fff,stroke:#333,stroke-width:2px
Prerequisites: Basic knowledge of Git and .NET or any programming language. An Azure DevOps organization (free tier available at dev.azure.com).
Core Concepts
Azure DevOps is organized around:
| Concept | Purpose |
|---|---|
| Organization | Top-level container for your company (e.g., dodatech) |
| Project | Contains repos, pipelines, boards, and artifacts for one product |
| Repository | Git source control |
| Pipeline | Automated build and release definition (YAML or classic) |
| Agent | The machine that runs pipeline jobs (Microsoft-hosted or self-hosted) |
| Artifact | Build output (e.g., .exe, .zip, .nupkg) |
| Release | Specific deployment of a build to an environment |
Building Your First Pipeline
Example 1: Simple .NET Build Pipeline
# azure-pipelines.yml
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
steps:
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '8.x'
- task: DotNetCoreCLI@2
displayName: 'Restore packages'
inputs:
command: 'restore'
projects: '**/*.csproj'
- task: DotNetCoreCLI@2
displayName: 'Build project'
inputs:
command: 'build'
projects: '**/*.csproj'
arguments: '--configuration $(buildConfiguration)'
- task: DotNetCoreCLI@2
displayName: 'Run tests'
inputs:
command: 'test'
projects: '**/*Tests.csproj'
arguments: '--configuration $(buildConfiguration) --collect "XPlat Code Coverage"'
- task: DotNetCoreCLI@2
displayName: 'Publish artifacts'
inputs:
command: 'publish'
publishWebProjects: false
projects: '**/DodaWeb/*.csproj'
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)'
zipAfterPublish: true
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'
Expected result: Every push to main triggers a build, test, and publish pipeline that outputs a deployable ZIP artifact.
Example 2: Multi-Stage Pipeline with Deployment
trigger:
- main
stages:
- stage: Build
jobs:
- job: BuildJob
pool:
vmImage: 'ubuntu-latest'
steps:
- script: echo "Building application..."
displayName: 'Build step'
- stage: Dev
dependsOn: Build
condition: succeeded()
jobs:
- deployment: DeployToDev
pool:
vmImage: 'ubuntu-latest'
environment: 'dev'
strategy:
runOnce:
deploy:
steps:
- script: echo "Deploying to Dev..."
- stage: Prod
dependsOn: Dev
condition: succeeded()
jobs:
- deployment: DeployToProd
pool:
vmImage: 'ubuntu-latest'
environment: 'prod'
strategy:
runOnce:
deploy:
steps:
- script: echo "Deploying to Production..."
Variable Groups and Secrets
variables:
- group: 'DodaTech-Production-Config'
- name: 'connectionString'
value: '$(ProdConnectionString)' # From Azure Key Vault via variable group
Variable groups keep secrets out of YAML. Link them to Azure Key Vault for automatic secret rotation.
Security Scanning in Pipelines
Integrate security into your CI/CD pipeline:
steps:
# Dependency scanning
- task: DotNetCoreCLI@2
displayName: 'Scan dependencies'
inputs:
command: 'custom'
custom: 'nuget'
arguments: 'audit'
# SAST (Static Analysis)
- task: CredScan@3
displayName: 'Credential Scanner'
# SBOM generation
- script: |
dotnet tool install --global Microsoft.SBOM.Tool
sbom-tool generate -b $(Build.ArtifactStagingDirectory) -bc $(Build.SourcesDirectory) -pn DodaWeb -pv 1.0.0
displayName: 'Generate SPDX SBOM'
Code Example: Build Status Badge
Add a pipeline status badge to your README:
[](https://dev.azure.com/dodatech/DodaWeb/_build)
Common Errors
YAML indentation errors: Azure DevOps YAML is strict. Use 2-space indentation consistently. A missing space causes
unexpected mappingerrors.Agent pool not found: Public projects may lose free parallel jobs. Check your organization settings under Parallel Jobs.
File not found in artifact staging: The
$(Build.ArtifactStagingDirectory)path must exist before you publish. Ensure your build step outputs files there.Pipeline not triggering on push: Check branch filters in
trigger:and ensure the YAML file is in the default branch (usuallymain).Secret variable visible in logs: By default, variable group secrets are masked. Mark them as
readonlyin the variable group to prevent override.Environment approval stuck: Production deployments often require manual approval. Check the environment settings in Azure DevOps â Pipelines â Environments.
Cross-project artifact access: To reference artifacts from another project's pipeline, use
resources.pipelinesin YAML instead of publishing to a feed.
Practice Questions
- What is the difference between a build pipeline and a release pipeline?
- How do you securely store connection strings used in pipelines?
- What does
dependsOndo in a multi-stage pipeline? - How do you trigger a pipeline only for changes to the
mainbranch? - What is the purpose of
PublishBuildArtifacts?
Answers:
- A build pipeline compiles and tests code; a release pipeline deploys build artifacts to environments. Modern YAML pipelines combine both.
- Use variable groups linked to Azure Key Vault. Reference secrets as
$(secretName)in YAML. - It specifies the stage that must complete before the current stage runs.
- Set
trigger: mainat the top of the YAML file. - It uploads build outputs (artifacts) to Azure DevOps so they can be used in subsequent stages or releases.
Challenge
Create a pipeline that builds a .NET MAUI app for Android and iOS, runs tests on both platforms, generates an SBOM, and deploys to App Center (or a staging server). Use matrix Strategy for parallel platform builds.
Real-World Task
Set up a CI/CD pipeline for an ASP.NET Core application that: (1) runs on every PR, (2) builds and tests, (3) runs OWASP dependency check, (4) deploys to a staging Azure App Service, and (5) sends a Teams webhook notification on success or failure.
Featured Snippet
What is Azure DevOps?
Azure DevOps is a Microsoft DevOps platform that provides Git Repository hosting, CI/CD pipelines, artifact management, test plans, and agile project management tools, enabling teams to automate software delivery from commit to deployment.
FAQ
Try It Yourself
What's Next
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro