- What Azure DevOps CI/CD Actually Does
- Step 1: Organize Your Azure DevOps Project
- Step 2: Write Your CI Pipeline in YAML
- Step 3: Add a Docker Build Stage for Containerized Workloads
- Step 4: Configure Your Release Pipeline (CD)
- Step 5: Secure Your Pipeline
- Step 6: Add Observability to Your Pipeline
- Common Mistakes Canadian Teams Make in 2026
- How This Applies to Telecom, Insurance, and Public Sector Workloads
- Getting Help With Your Pipeline Setup
- Frequently Asked Questions
Slow releases cost you more than time. In telecom, insurance, and the public sector, a broken deployment process means delayed features, compliance exposure, and stakeholders losing confidence in your team. A well-configured Azure DevOps CI/CD pipeline removes that friction — giving your team a repeatable, auditable path from code commit to production.
This guide walks through the practical steps to set up that pipeline in 2026, with specific considerations for Canadian organizations running enterprise workloads on .NET, Angular, and containerized infrastructure.
What Azure DevOps CI/CD Actually Does
CI/CD stands for Continuous Integration and Continuous Delivery (or Deployment). The two stages serve distinct purposes.
Continuous Integration (CI) automatically builds and tests your code every time a developer pushes a change. It catches integration errors early, before they compound into something harder to fix.
Continuous Delivery (CD) takes a successfully built artifact and deploys it to a target environment — staging, UAT, or production — based on rules your team defines.
Azure DevOps ties these stages together through Pipelines. Your pipeline lives in a YAML file, version-controlled alongside your application code, and triggered by events like pull requests or merges to a release branch.
Step 1: Organize Your Azure DevOps Project
Before writing a single line of YAML, get your project structure right.
Create a dedicated organization for your company inside Azure DevOps if you don't already have one. Under that organization, create a project. Each project contains Repos (source code), Pipelines (CI/CD), Boards (work items), and Artifacts (package feeds).
For teams managing multiple services, use one Azure DevOps organization with separate projects per product line or business unit. This keeps permissions clean and makes audit trails easier to manage — both of which matter in regulated environments.
Connect your repository. Azure DevOps supports its own Git hosting through Azure Repos, as well as GitHub and Bitbucket. For most Canadian enterprise teams already inside the Microsoft ecosystem, Azure Repos is the natural fit.
Step 2: Write Your CI Pipeline in YAML
Create a file called azure-pipelines.yml at the root of your repository. This file defines your build pipeline.
Here is a working example for a .NET 8 application:
trigger:
branches:
include:
- main
- release/*
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
steps:
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '8.x'
- script: dotnet restore
displayName: 'Restore dependencies'
- script: dotnet build --configuration $(buildConfiguration)
displayName: 'Build'
- script: dotnet test --configuration $(buildConfiguration) --no-build
displayName: 'Run tests'
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: '$(Build.ArtifactStagingDirectory)'
artifactName: 'drop'
This pipeline triggers on pushes to main or any release/* branch. It restores dependencies, builds in Release mode, runs your test suite, and publishes the artifact for the CD stage to consume.
For Angular front-end applications, swap the .NET tasks for Node.js steps: install Node, run npm ci, run ng build --configuration production, and publish the dist/ folder as an artifact.
Step 3: Add a Docker Build Stage for Containerized Workloads
If your application runs in containers, extend your CI pipeline to build and push a Docker image to Azure Container Registry (ACR).
- task: Docker@2
displayName: 'Build and push image'
inputs:
containerRegistry: 'your-acr-service-connection'
repository: 'your-app-name'
command: 'buildAndPush'
Dockerfile: '**/Dockerfile'
tags: |
$(Build.BuildId)
latest
Tag images with the build ID, not just latest. This gives you a traceable artifact you can roll back to if a production deployment causes issues. In telecom and insurance environments, that traceability is not optional.
Step 4: Configure Your Release Pipeline (CD)
The CD stage deploys your artifact. You can define it in the same YAML file using stages, or use Azure DevOps Release Pipelines — the classic UI-based approach. YAML stages are the better choice for teams that want everything version-controlled.
A typical multi-stage pipeline looks like this:
stages:
- stage: Build
jobs:
- job: BuildJob
steps:
# your CI steps here
- stage: DeployStaging
dependsOn: Build
condition: succeeded()
jobs:
- deployment: DeployToStaging
environment: 'staging'
strategy:
runOnce:
deploy:
steps:
- script: echo "Deploy to staging"
- stage: DeployProduction
dependsOn: DeployStaging
condition: succeeded()
jobs:
- deployment: DeployToProduction
environment: 'production'
strategy:
runOnce:
deploy:
steps:
- script: echo "Deploy to production"
The environment keyword is worth paying attention to. Environments let you configure approval gates — so before anything reaches production, you can require a manual sign-off from a lead engineer or change manager. That's standard practice in public sector and insurance delivery, and Azure DevOps makes it straightforward to enforce.
Step 5: Secure Your Pipeline
Security in a CI/CD pipeline is a delivery requirement, not an afterthought.
Use service connections, not hardcoded credentials. Azure DevOps service connections store credentials securely and let you control which pipelines can access which resources.
Store secrets in Azure Key Vault. Reference them in your pipeline using the AzureKeyVault@2 task. API keys, connection strings, and certificates have no place in a YAML file.
Restrict pipeline permissions. Scope each pipeline to specific repositories and environments. A pipeline that deploys to staging should not have permission to deploy to production.
Enable branch policies. Require pull request reviews and passing CI checks before merging to main or release branches. This keeps broken code out of your delivery stream.
For organizations subject to Canadian data residency requirements, confirm that your Azure DevOps organization and connected services are hosted in a Canadian Azure region — Canada Central or Canada East.
Step 6: Add Observability to Your Pipeline
A pipeline that deploys without visibility is one you can't fully trust.
Integrate OpenTelemetry instrumentation into your application build so that traces and metrics flow into your monitoring platform from the first deployment. If your team uses Dynatrace or Splunk, configure the relevant Azure DevOps extensions to push deployment markers into those tools. A deployment marker tells your monitoring platform exactly when a new version went live — which makes it much faster to correlate an error spike with a specific release.
Add a post-deployment health check to your production stage as well. A simple HTTP probe against a /health endpoint should fail the pipeline and trigger a rollback or alert if it returns a non-200 status. Don't rely on manual monitoring to catch a bad deploy.
Common Mistakes Canadian Teams Make in 2026
Skipping environment separation. Running the same pipeline configuration against staging and production without environment-specific variable groups leads to configuration drift and failures that are difficult to diagnose.
Using latest as the only image tag. You lose the ability to roll back to a specific build. Always tag with the build ID.
Not gating production deployments. In regulated industries, an unreviewed deployment to production is a compliance risk. Approval gates in Azure DevOps environments cost nothing to configure and prevent a significant number of problems.
Treating the pipeline as a black box. If your team can't read the YAML and explain what each step does, that's a knowledge gap that will surface during an incident. Keep pipeline definitions simple, well-commented, and reviewed in pull requests like any other code.
Ignoring pipeline run times. A CI pipeline that takes 40 minutes to complete slows down your entire team. Profile your build steps, parallelize test runs where possible, and cache dependency restores.
How This Applies to Telecom, Insurance, and Public Sector Workloads
The mechanics of Azure DevOps CI/CD are consistent across industries. The constraints are not.
In telecom, order management systems often carry complex integration dependencies. Your pipeline needs to run integration tests against mocked downstream APIs before any deployment reaches a shared environment.
In insurance, audit trails are non-negotiable. Azure DevOps keeps a full history of pipeline runs, approvals, and artifact versions — and that history becomes your evidence during a compliance review.
In the public sector, formal change management processes often require approval before production deployment. Azure DevOps environments with required approvals map directly to that process without adding manual overhead.
These aren't theoretical scenarios. They reflect the delivery constraints that teams at organizations like Bell and Desjardins navigate on every release cycle.
Getting Help With Your Pipeline Setup
Getting the configuration right the first time saves weeks of rework. If your team is managing legacy systems, a modernization mandate, or a regulated delivery environment, the decisions you make early in the pipeline design matter more than the syntax.
Hamdi Services works with Canadian organizations in telecom, insurance, and the public sector to design and implement CI/CD pipelines that fit your existing toolchain and compliance requirements. Every engagement is tied to measurable delivery outcomes from the first sprint.
Ready to scope your project? Plan a discovery call at hamdiservices.ca/en/contact.
Frequently Asked Questions
What is an Azure DevOps CI/CD pipeline?
An automated workflow that builds, tests, and deploys your application code whenever a change is pushed to a repository. The CI stage handles building and testing. The CD stage handles deployment to one or more environments.
How do I trigger an Azure DevOps pipeline automatically?
Define triggers in your azure-pipelines.yml file. The trigger block specifies which branches cause the pipeline to run. You can also configure pull request triggers using the pr block, so the pipeline runs on every proposed change before it is merged.
How do I add manual approval gates before a production deployment?
Create an Environment for your production stage inside Azure DevOps. Within that environment, add an Approvals and Checks rule. You can require one or more named users or groups to approve before the deployment proceeds.
Can I use Azure DevOps with Docker and Kubernetes?
Yes. Azure DevOps includes built-in tasks for building Docker images, pushing to Azure Container Registry, and deploying to Azure Kubernetes Service. You can also deploy to self-hosted Kubernetes clusters using Helm or kubectl tasks.
How do I store secrets securely in an Azure DevOps pipeline?
Use Azure Key Vault to store secrets, then reference them in your pipeline with the AzureKeyVault@2 task. You can also use Azure DevOps variable groups linked to a Key Vault. Never hardcode credentials in YAML files.
What is the difference between Classic Release Pipelines and YAML pipelines in Azure DevOps?
Classic Release Pipelines use a graphical UI configured through the Azure DevOps web interface. YAML pipelines define the entire pipeline as code stored in your repository. YAML pipelines are version-controlled, easier to review, and the recommended approach for new projects in 2026.
How long does it take to set up a production-ready Azure DevOps CI/CD pipeline?
A basic pipeline for a single application can be configured in a day. A production-ready pipeline with environment gates, secret management, Docker builds, and observability integration typically takes two to five days, depending on application complexity and the number of environments involved.

